代码改变世界

使用ConcurrentDictionary实现轻量缓存

2015-07-30 15:43  Nicolas.wang  阅读(1074)  评论(0编辑  收藏  举报

项目中需要用到一个轻量缓存,存储重复使用的数据。
在设计中需要考虑:
1.做成通用组件,为未来其他模块方法操作结果做准备。
2.缓存模块需要接口化,为未来替换使用外部缓存做准备。
3.使用默认缓存过期时间,单个Key的过期时间可以自由配置。

使用ConcurrentDictionary来作为我们的缓存容器,并能保证线程安全。

 1     public interface IDataCache
 2     {
 3         TimeSpan Ttl
 4         {
 5             get;
 6         }
 7 
 8         void Set(string key, object value);
 9 
10         void Set(string key, object value, TimeSpan ttl);
11 
12         object Get(string key);
13 
14         void PurgeExpiredEntries();
15     }
  1     /// <summary>
  2     /// An implementation of <see cref="IDataCache"/> which uses a dictionary to cache values in memory.
  3     /// </summary>
  4     public class InMemDataCache:IDataCache
  5     {
  6         private static readonly TimeSpan DefaultTtl = TimeSpan.FromMinutes(10);
  7 
  8         private readonly TimeSpan _ttl;
  9         private readonly ConcurrentDictionary<string, CacheEntry> _cache = new ConcurrentDictionary<string, CacheEntry>();
 10 
 11         /// <summary>
 12         /// Initialize a new instance of <see cref="InMemDataCache"/> using the default TTL.
 13         /// </summary>
 14         public InMemDataCache()
 15             : this(DefaultTtl)
 16         {
 17             
 18         }
 19 
 20         /// <summary>
 21         /// Initialize a new instance of <see cref="InMemDataCache"/> using a specified TTL.
 22         /// </summary>
 23         /// <param name="ttl">
 24         /// The time-to-live (TTL) of value saved into the cache. Zero or negative value indicates that values shall never expire.
 25         /// </param>
 26         public InMemDataCache(TimeSpan ttl)
 27         {
 28             _ttl = ttl;
 29         }
 30 
 31         /// <summary>
 32         /// The time-to-live (TTL) of value saved into the cache.
 33         /// </summary>
 34         public TimeSpan Ttl
 35         {
 36             get
 37             {
 38                 return _ttl;
 39             }
 40         }
 41 
 42         /// <summary>
 43         /// Save a key-value pair into the cache using the global TTL settings.
 44         /// Existed value associated with the specified key shall be overwritten.
 45         /// </summary>
 46         /// <param name="key"></param>
 47         /// <param name="value"></param>
 48         public void Set(string key, object value)
 49         {
 50             Set(key, value, _ttl);
 51         }
 52 
 53         /// <summary>
 54         /// Save a key-value pair into the cache using the global TTL settings.
 55         /// Existed value associated with the specified key shall be overwritten.
 56         /// </summary>
 57         /// <param name="key"></param>
 58         /// <param name="value"></param>
 59         /// <param name="ttl">
 60         /// The time-to-live (TTL) of value saved into the cache. Zero or negative value indicates that values shall never expire.
 61         /// </param>
 62         public void Set(string key, object value, TimeSpan ttl)
 63         {
 64             var expirationTime = ttl <= TimeSpan.Zero ? DateTime.MinValue : DateTime.Now.Add(ttl);
 65             var result = new CacheEntry(value, expirationTime);
 66             _cache.AddOrUpdate(key, result, (k, o) => result);
 67         }
 68 
 69         public object Get(string key)
 70         {
 71             CacheEntry entry;
 72             if (!_cache.TryGetValue(key, out entry))
 73             {
 74                 return null;
 75             }
 76 
 77             if (entry.ExpirationTime == DateTime.MinValue || DateTime.Now < entry.ExpirationTime)
 78             {
 79                 return entry.Value;
 80             }
 81 
 82             CacheEntry old;
 83             _cache.TryRemove(key, out old);
 84             return null;
 85         }
 86 
 87         public void PurgeExpiredEntries()
 88         {
 89             foreach (var key in _cache.Keys)
 90             {
 91                 Get(key);
 92             }
 93         }
 94 
 95         private class CacheEntry
 96         {
 97             public readonly object Value;
 98             public readonly DateTime ExpirationTime;
 99 
100             public CacheEntry(object value, DateTime expirationTime)
101             {
102                 // TODO: Complete member initialization
103                 Value = value;
104                 ExpirationTime = expirationTime;
105             }
106         }
107     }

 完整demo路径:https://files.cnblogs.com/files/Nicolas-wang/Examples.Cache.zip