Memcach、WebCache、MemoryCache缓存帮助类

    技术2022-07-15  85

    Memcach、WebCache、MemoryCache缓存帮助类

    场景说明使用方法业务层的缓存类实例化接口ICacheMgrMemcachMgr 实现WebCacheMgr 的实现MemoryCacheMgr 的实现

    场景说明

    项目中使用的缓存各用各的,难以统一,所以封装一下,一来方便使用,二来统一调用,以后想改用其它缓存方式也不用整个项目大改。

    使用方法

    CacheKey.cache["key"] = 123;//写入 CacheKey.cache["key", 60] = 123;//写入 CacheKey.cache["key", DateTime.Now.AddMinutes(60)] = 123;//写入 var obj1 = CacheKey.cache["key"];//读取 var obj2 = CacheKey.cache.GetCache<object>("key", 60, delegate { return new object(); });//读取(缓存不存在时通过回调获取) var obj3 = CacheKey.cache.GetCache<object>("key", DateTime.Now.AddMinutes(60), delegate { return new object(); });//读取(缓存不存在时通过回调获取) CacheKey.cache.Remove("key");//删除 CacheKey.cache.Clear();//清空

    业务层的缓存类实例化

    这里主要是让所有成员包括自己记住自己都用了什么缓存key,尽量防止被其它地方的代码通过key覆盖缓存,这种错误虽然少,但一出现就很难排查。这里用的是简单单例模式

    public class CacheKey { /// <summary> /// 缓存类实例成员,全局唯一。要更新缓存实现方式时请使用其它实现ICacheMgr接口的类 /// </summary> public static readonly ICacheMgr cache = new MemoryCacheMgr(); public static readonly string Cagetory = "XSite_Cagetory_Cache"; /// <summary> /// /// </summary> /// <returns></returns> internal static string GetXxxxKey() { return "XxxxKey"; } }

    接口ICacheMgr

    规范化缓存封装的实现方式

    public interface ICacheMgr { /// <summary> /// 根据key,设置、获取值。核心方法 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间(单位分钟),获取时该参数无效</param> /// <returns>缓存副本</returns> object this[string key, int duration] { get; set; } /// <summary> /// 根据key,设置、获取值 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,单位分钟,获取时该参数无效</param> /// <returns></returns> object this[string key, DateTime duration] { get; set; } /// <summary> /// 根据key,设置、获取值。并设置默认过期时间为60分钟 /// </summary> /// <param name="key"></param> /// <returns>缓存副本</returns> object this[string key] { get; set; } /// <summary> /// 返回key是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> bool KeyExists(string key); /// <summary> /// 移除缓存 /// </summary> /// <param name="key"></param> void Remove(string key); /// <summary> /// 移除所有缓存,成功返回true /// </summary> /// <returns></returns> bool Clear(); /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定到 expiry 时过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="expiry">过期时间</param> /// <param name="action"></param> /// <returns></returns> T GetCache<T>(string key, DateTime expiry, Func<T> action); /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定 duration 分钟后过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="duration">过期时间(单位分钟)</param> /// <param name="action"></param> /// <returns></returns> T GetCache<T>(string key, int duration, Func<T> action); /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> T GetCache<T>(string key, T def = default(T)); }

    MemcachMgr 实现

    using Memcached.ClientLibrary; /// <summary> /// Memcach缓存类 /// </summary> public class MemcachMgr : ICacheMgr { private static MemcachedClient _client; private static readonly object LockObj = new object(); /// <summary> /// 初始化 /// </summary> static MemcachMgr() { string memcachIpAndPort = System.Configuration.ConfigurationManager.AppSettings["MemcachIpAndPort"] ?? string.Empty; string memcachPoolName = System.Configuration.ConfigurationManager.AppSettings["MemcachPoolName"] ?? string.Empty; string[] ipANdPorts = memcachIpAndPort.Split(','); if (ipANdPorts.Length == 0) { throw new Exception("请在 .config 中添加 appSettings MemcachIpAndPort 的配置"); } Initialize(ipANdPorts, memcachPoolName); } private static void Initialize(string[] serverList, string poolName) { var pool = SockIOPool.GetInstance(poolName); pool.SetServers(serverList);//设置服务器列表 pool.SetWeights(new int[] { 1 });//各服务器之间负载均衡的设置比例 pool.InitConnections = 1;//初始化时创建连接数 pool.MinConnections = 1;//最小连接数 pool.MaxConnections = 500;//最大连接数 pool.MaxIdle = 1000 * 60 * 60 * 6;//连接的最大空闲时间,下面设置为6个小时(单位ms),超过这个设置时间,连接会被释放掉 pool.SocketConnectTimeout = 500;//socket连接的超时时间,下面设置表示不超时(单位ms),即一直保持链接状态 pool.SocketTimeout = 1000*3;//通讯的超时时间,下面设置为3秒(单位ms) pool.MaintenanceSleep = 30;//维护线程的间隔激活时间,下面设置为30秒(单位s),设置为0时表示不启用维护线程 pool.Failover = true;//表示对于服务器出现问题时的自动修复。 pool.Nagle = false;//是否对TCP/IP通讯使用nalgle算法 pool.MaxBusy = 1000 * 30;//socket单次任务的最大时间(单位ms),超过这个时间socket会被强行中端掉,当前任务失败。 pool.Initialize();//容器初始化 lock (LockObj) { if (_client == null) { _client = new MemcachedClient { PoolName = poolName }; } } } /// <summary> /// 根据key,设置、获取值 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,单位分钟,获取时该参数无效</param> /// <returns></returns> public object this[string key, int duration] { get { return this[key, default(DateTime)]; } set { this[key, DateTime.Now.AddMinutes(duration)] = value; } } /// <summary> /// 根据key,设置、获取值。核心方法 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,获取时该参数无效</param> /// <returns></returns> public object this[string key, DateTime duration] { get { return _client.Get(key); } set { if (value == null) Remove(key); else { _client.Set(key, value, duration); } } } /// <summary> /// 根据key,设置、获取值。并设置默认过期时间为60分钟 /// </summary> /// <param name="key"></param> /// <returns></returns> public object this[string key] { get { return this[key, default(DateTime)]; } set { this[key, DateTime.Now.AddMinutes(60)] = value; } } /// <summary> /// 返回key是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> public bool KeyExists(string key) { return _client.KeyExists(key); } /// <summary> /// 移除缓存 /// </summary> /// <param name="key"></param> public void Remove(string key) { _client.Delete(key); } /// <summary> /// 移除所有缓存,成功返回true /// </summary> /// <returns></returns> public bool Clear() { return _client.FlushAll(); } /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定 duration 分钟后过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="duration">过期时间(单位分钟)</param> /// <param name="action"></param> /// <returns></returns> public T GetCache<T>(string key, DateTime expiry, Func<T> action) { if (action == null) { throw new ArgumentNullException("action"); } object obj = this[key]; if (obj == null) { obj = action(); if (obj != null) this[key, expiry] = obj; } if (obj == null) return default(T);//obj为null,肯定是 action 没返回值 return (T)obj; } /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定到 expiry 时过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="expiry">过期时间</param> /// <param name="action"></param> /// <returns></returns> public T GetCache<T>(string key, int duration, Func<T> action) { return GetCache<T>(key, DateTime.Now.AddMinutes(duration), action); } /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(string key, T def = default(T)) { object obj = this[key]; if (obj == null) return def;//obj为null,肯定是 action 没返回值 try { return (T)obj; } catch { return def; } } }

    WebCacheMgr 的实现

    using System.Web.Caching; /// <summary> /// HttpContext.Current.Cache 的封装 /// </summary> public partial class WebCacheMgr : ICacheMgr { private static volatile System.Web.Caching.Cache cache = HttpRuntime.Cache; /// <summary> /// 根据key,设置、获取值。 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,获取时该参数无效</param> /// <returns>缓存副本</returns> public object this[string key, DateTime duration] { get { return this[key, 0]; } set { if (duration == default(DateTime) || value == null) { cache.Remove(key); } else { //if (duration < DateTime.Now) throw new Exception("参数 duration 必须大于当前时间"); int dMin = (int)(duration - DateTime.Now).TotalMinutes; if (dMin > 0) { this[key, dMin] = value; } } } } /// <summary> /// 根据key,设置、获取值。核心方法 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,单位分钟,获取时该参数无效</param> /// <returns></returns> public object this[string key, int duration] { get { object obj = cache.Get(key); return ToolX.Clone(obj);//防止外部对缓存内容更改而复制一份,做的和Memcach一样 //复制方法实现 https://blog.csdn.net/Sunsame_Wei/article/details/107085177 } set { if (null == value) { cache.Remove(key); return; } int seconds = duration * 60; if (seconds <= 0) { cache.Insert(key, value, null, DateTime.MaxValue, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); } else { cache.Insert(key, value, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); } } } /// <summary> /// 根据key,设置、获取值。并设置默认过期时间为60分钟 /// </summary> /// <param name="key"></param> /// <returns>缓存副本</returns> public object this[string key] { get { return this[key, default(DateTime)]; } set { this[key, (60)] = value; } } /// <summary> /// 返回key是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> public bool KeyExists(string key) { return cache.Get(key) != null; } /// <summary> /// 移除缓存 /// </summary> /// <param name="key"></param> public void Remove(string key) { cache.Remove(key); } /// <summary> /// 移除所有缓存,成功返回true /// </summary> /// <returns></returns> public bool Clear() { List<string> ls = new List<string>(); foreach (System.Collections.DictionaryEntry k in cache) { if (k.Key != null) { ls.Add(k.Key.ToString()); } } foreach (var k in ls) { cache.Remove(k); } return true; } /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定 duration 分钟后过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="duration">过期时间(单位分钟)</param> /// <param name="action"></param> /// <returns></returns> public T GetCache<T>(string key, DateTime expiry, Func<T> action) { if (action == null) { throw new ArgumentNullException("action"); } object obj = this[key]; if (obj == null) { obj = action(); if (obj != null) this[key, expiry] = obj; } if (obj == null) return default(T);//obj为null,肯定是 action 没返回值 return (T)obj; } /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定到 expiry 时过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="expiry">过期时间</param> /// <param name="action"></param> /// <returns></returns> public T GetCache<T>(string key, int duration, Func<T> action) { return GetCache<T>(key, DateTime.Now.AddMinutes(duration), action); } /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(string key, T def = default(T)) { object obj = this[key]; if (obj == null) return def;//obj为null try { return (T)obj; } catch { return def; } } }

    MemoryCacheMgr 的实现

    using System.Runtime.Caching; /// <summary> /// System.Runtime.Caching.MemoryCache 的封装 /// </summary> public partial class MemoryCacheMgr : ICacheMgr { /// <summary> /// 根据key,设置、获取值。核心方法 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,获取时该参数无效</param> /// <returns>缓存副本</returns> public object this[string key, DateTime duration] { get { object obj = MemoryCache.Default.Get(key); return ToolX.Clone(obj);//防止外部对缓存内容更改而复制一份,做的和Memcach一样 //复制方法实现 https://blog.csdn.net/Sunsame_Wei/article/details/107085177 } set { MemoryCache.Default.Set(key, value, DateTimeOffset.Now.Add(duration - DateTime.Now), null); } } /// <summary> /// 根据key,设置、获取值。 /// </summary> /// <param name="key"></param> /// <param name="duration">仅用于设置过期时间,单位分钟,获取时该参数无效</param> /// <returns></returns> public object this[string key, int duration] { get { return this[key, default(DateTime)]; } set { if (duration <= 0 || value == null) { MemoryCache.Default.Remove(key); } else { this[key, DateTime.Now.AddMinutes(duration)] = value; } } } /// <summary> /// 根据key,设置、获取值。并设置默认过期时间为60分钟 /// </summary> /// <param name="key"></param> /// <returns>缓存副本</returns> public object this[string key] { get { return this[key, default(DateTime)]; } set { this[key, (60)] = value; } } /// <summary> /// 返回key是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> public bool KeyExists(string key) { return MemoryCache.Default.Get(key) != null; } /// <summary> /// 移除缓存 /// </summary> /// <param name="key"></param> public void Remove(string key) { MemoryCache.Default.Remove(key); } /// <summary> /// 移除所有缓存,成功返回true /// </summary> /// <returns></returns> public bool Clear() { List<string> ls = new List<string>(); foreach (var k in MemoryCache.Default) { ls.Add(k.Key); } foreach (var k in ls) { MemoryCache.Default.Remove(k); } return true; } /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定 duration 分钟后过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="duration">过期时间(单位分钟)</param> /// <param name="action"></param> /// <returns></returns> public T GetCache<T>(string key, DateTime expiry, Func<T> action) { if (action == null) { throw new ArgumentNullException("action"); } object obj = this[key]; if (obj == null) { obj = action(); if (obj != null) this[key, expiry] = obj; } if (obj == null) return default(T);//obj为null,肯定是 action 没返回值 return (T)obj; } /// <summary> /// 获取缓存,当缓存不存在时使用 action 来创建缓存并设定到 expiry 时过期 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">缓存key</param> /// <param name="expiry">过期时间</param> /// <param name="action"></param> /// <returns></returns> public T GetCache<T>(string key, int duration, Func<T> action) { return GetCache<T>(key, DateTime.Now.AddMinutes(duration), action); } /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(string key, T def = default(T)) { object obj = this[key]; if (obj == null) return def;//obj为null try { return (T)obj; } catch { return def; } } }

    原文链接:http://blog.albsz.cn/2020-07-03-forcache.html

    Processed: 0.017, SQL: 10