c#使用StackExchange.Redis封装Redis帮助类示例代码

知道91 | ASP.NET | 2017-10-24 | 阅读:5154

在面向对象编程的过程中为了减轻数据库的压力通常会采用缓存。使用C#编程的时候我们可以使用.NET自带的缓存 System.Web.HttpRuntime.Cache,但是自带的缓存是不支持分布式部署的,并且还有其他缺点可以自行Google一下。现在比较流行的分布是缓存有Memcached和Redis。这两个缓存你都可以看成是key-value的nosql数据库,支持持久化。

Memcached和Redis数据类型比较

Redis最为常用的数据类型主要有以下:

  • String
  • Hash
  • List
  • Set
  • Sorted set

Memcached仅支持简单的key-value结构的数据

平时我们一般使用Redis的String就可以了,本文重点讲解的是通过StackExchange.Redis使用C#封装Redis的帮助类Helper。

如果我们的程序中需要使用缓存,然而使用什么样的形式缓存(是C#自带的、Memcached还是Redis)是有可能变动的,因此我们需要针对是根据接口来编程,而不是具体某一个缓存的实现,首先我们定义如下的缓存接口:

ICache.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Framework.Common.CacheHelper
{
    public interface ICache
    {
        T StringGet(string key,Funcfunc, TimeSpan absoluteExpireTime, bool cache = true) where T : class;
    }
}

然后实现ICache接口的Redis缓存。

RedisCache.cs

using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Framework.Common.CacheHelper
{
    public class RedisCache : ICache
    {
        public T StringGet(string key, Funcfunc, TimeSpan absoluteExpireTime ,bool cache = true)  where T: class
        {
            if (!cache)
                return func.Invoke();

            if(RedisManager.Instance.GetDatabase().KeyExists(key))
            {
                string strVal = RedisManager.Instance.GetDatabase().StringGet(key);
                return string.IsNullOrEmpty(strVal) ? null : JsonConvert.DeserializeObject(strVal);
            }
            else
            {
                var obj = func.Invoke();
                RedisManager.Instance.GetDatabase().StringSet(key, JsonConvert.SerializeObject(obj), absoluteExpireTime);
                return obj;
            }
        }
    }
}

其中RedisManager.cs的代码如下所示

using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Framework.Common.CacheHelper
{
    public class RedisManager
    {
        private static volatile ConnectionMultiplexer _instance;
        private static volatile object sys_object = new object();
        private static string _conn = ConfigurationManager.AppSettings["redis_config"] ?? "127.0.0.1:6379";
        private RedisManager() { }

        public static ConnectionMultiplexer Instance
        {
            get
            {
                if(_instance==null)
                {
                    lock(sys_object)
                    {
                        if(_instance==null)
                        {
                            _instance = ConnectionMultiplexer.Connect(_conn);
                        }
                    }
                }
                return _instance;
            }
        }

        public static IDatabase GetDatabase()
        {
            return _instance.GetDatabase();
        }
    }
}

注意ConnectionMultiplexer只需要创建一个实例,所以RedisManager.cs采用的是单例模式

现在已经封装好了所有的实现类,但是这样Redis.cs还需要自己实现,那么使用的时候就不方便,为此我们可以封装一个Cache的工厂类来实现具体缓存的实例化,具体代码如下所示:

CacheManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Framework.Common.CacheHelper
{
    public static class CacheManager
    {
        private static volatile ICache _instance = null;
        private static volatile object sys_obj = new object();

        public static ICache Cache
        {
            get
            {
                if(_instance ==null )
                {
                    lock(sys_obj)
                    {
                        if(_instance == null)
                        {
                            _instance =  new RedisCache();
                        }
                    }
                }
                return _instance;
            }
        }
    }
}

这样我们就可以直接通过CacheManager直接使用缓存类了,客户代码就无需去关心具体缓存类的实例。

以上就是通过StackExchange.Redis,使用C#封装Redis帮助类的示例代码。做到的实现对修改的封闭,对扩展的开放。