用到缓存架构,我们一般都会想到的Redis,因为它支持分布式,高可用,速率非常快。MemoryCache则相对较少提到,但是对于单体项目或者小型项目,memorycache还是是不错的选择。MemoryCache是netcore中集成的缓存架构,使用起来非常的简单方便。
meorycache简单的代码封装
1 /// <summary> 2 /// memorycache管理类 3 /// </summary> 4 public class MemoryCacheManagement 5 { 6 public static MemoryCacheManagement Default = new MemoryCacheManagement(); 7 8 private IMemoryCache _cache = new MemoryCache(new MemoryCacheOptions()); 9 private MemoryCacheManagement() 10 { 11 12 } 13 14 /// <summary> 15 /// 设置缓存,不设置超时时间 16 /// </summary> 17 /// <typeparam name="T"></typeparam> 18 /// <param name="key"></param> 19 /// <param name="value"></param> 20 public void SetValue<T>(string key, T value) 21 { 22 if (string.IsNullOrEmpty(key)) 23 { 24 throw new ArgumentNullException("key"); 25 } 26 T t; 27 if (_cache.TryGetValue<T>(key, out t)) 28 { 29 _cache.Remove(key); 30 } 31 _cache.Set(key, value); 32 } 33 /// <summary> 34 /// 设置缓存,并指定绝对超时时间 35 /// </summary> 36 /// <typeparam name="T"></typeparam> 37 /// <param name="key"></param> 38 /// <param name="value"></param> 39 /// <param name="absoluteTimeoutSeconds"></param> 40 public void SetValue<T>(string key, T value, int absoluteTimeoutSeconds) 41 { 42 if (string.IsNullOrEmpty(key)) 43 { 44 throw new ArgumentNullException("key"); 45 } 46 T t; 47 if (_cache.TryGetValue<T>(key, out t)) 48 { 49 _cache.Remove(key); 50 } 51 _cache.Set<T>(key, value, DateTimeOffset.Now.AddSeconds(absoluteTimeoutSeconds)); 52 } 53 /// <summary> 54 /// 设置缓存,并设定超时时间,不访问(滑动)超时时间 55 /// </summary> 56 /// <typeparam name="T"></typeparam> 57 /// <param name="key"></param> 58 /// <param name="value"></param> 59 /// <param name="absoluteTimeoutSeconds"></param> 60 /// <param name="slidingExpirationSeconds"></param> 61 public void SetValue<T>(string key, T value, int absoluteTimeoutSeconds, int slidingExpirationSeconds) 62 { 63 if (string.IsNullOrEmpty(key)) 64 { 65 throw new ArgumentNullException("key"); 66 } 67 T t; 68 if (_cache.TryGetValue<T>(key, out t)) 69 { 70 _cache.Remove(key); 71 } 72 _cache.Set(key, value, new MemoryCacheEntryOptions() 73 { 74 AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(absoluteTimeoutSeconds), //绝对超时时间, 75 SlidingExpiration = TimeSpan.FromSeconds(slidingExpirationSeconds), //不访问超时时间(在这个指定的时段内没有使用则过期,否则顺延) 76 }); 77 } 78 /// <summary> 79 /// 获取缓存值 80 /// </summary> 81 /// <typeparam name="T"></typeparam> 82 /// <param name="key"></param> 83 /// <returns></returns> 84 public T GetValue<T>(string key) 85 { 86 if (string.IsNullOrEmpty(key)) 87 { 88 throw new ArgumentNullException("key"); 89 } 90 T val = default(T); 91 _cache.TryGetValue<T>(key, out val); 92 return val; 93 94 } 95 96 /// <summary> 97 /// 判断缓存是否存在 98 /// </summary> 99 /// <param name="key"></param> 100 /// <returns></returns> 101 public bool CheckExists(string key) 102 { 103 if (string.IsNullOrEmpty(key)) 104 { 105 throw new ArgumentNullException("key"); 106 } 107 object val ; 108 return _cache.TryGetValue(key, out val); 109 } 110 /// <summary> 111 /// 清楚缓存值 112 /// </summary> 113 /// <param name="key"></param> 114 public void Remove(string key) 115 { 116 if (string.IsNullOrEmpty(key)) 117 { 118 throw new ArgumentNullException("key"); 119 } 120 _cache.Remove(key); 121 } 122 /// <summary> 123 /// 获取所有的Key 124 /// </summary> 125 /// <returns></returns> 126 public List<string> GetAllKey() 127 { 128 //TODO获取所有缓存key 129 throw new Exception("暂不用到,未实现"); 130 } 131 /// <summary> 132 /// 获取所有的value 133 /// </summary> 134 /// <returns></returns> 135 public List<object> GetAllValue() 136 { 137 //TODO获取所有缓存值 138 throw new Exception("暂不用到,未实现"); 139 } 140 }
以上就是MemorCache的简单封装实现,设置成单例使用起来还是比较简洁的。
但是对于MemoryCache的一些注意事项,我们还是需要弄清楚的
过期时间:
AbsoluteExpiration:绝对过期时间,超过指定的过期时间后再获取,或者压缩操作则会触发该缓存key过期
SlidingExpiration:滑动过期时间,再绝对过期时间范围内,在滑动过期时间范围内有调用该key,则滑动事件将重新记时,否则过期。
注意:memorycache的过期时间不是由定时任务或者线程实现的,而是通过有访问时触发判断是否过期,过期则删除(同时触发过期回调事件)。
MemoryCacheOptions参数:
缓存大小限制(SizeLimit)、压缩比例(ExpirationScanFrequency)、缓存权重(Priority)、过期扫描频率(ExpirationScanFrequency)
缓存大小限制:限制缓存的最大容量,当超过该容量时则触发压缩,移除部分数据,优先移除权重较低的。
压缩比例:触发压缩时,压缩的目标比例。
缓存权重:缓存的优先级别
过期扫描频率:其实它的机制跟它字面意义还是有些出入的,过期扫描频率是建立在有访问的前提下的。只有访问缓存了才可能会触发这个扫描,默认一分钟(也就是最快时是一分钟扫描一次)