Memcach、WebCache、MemoryCache缓存帮助类

场景说明

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

使用方法

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值