公司一直在用.net自带的缓存,大家都知道.net自带缓存的缺点,就不多说了,不知道的可以查一查,领导最近在说分布式缓存,我们选的是redis,领导让我不忙的时候封装一下,搜索了两天,选了选第三方的插件,ServiceStack.Redis和StackExchange.Redis以前都用过,不过都是别人封装好的,今天在往项目中整合的时候,我使用的ServiceStack.Redis版本不兼容.net 4.0,在网上找了一圈,ServiceStack.Redis对.net 4.0的支持用起来很麻烦,要改变系统引用的东西,最后放弃了,今天又拿NServiceKit.Redis重新封装了一下,下一篇在说NServiceKit.Redis。先说说ServiceStack.Redis,ServiceStack.Redis是Redis官方推荐的C#客户端,性能非常优越,使用也很方便,但是从v4版本已经逐渐商业化了,普通版每小时只能访问Redis 6000次,我没测试过,大家可以看看这篇文章http://blog.csdn.net/u010533180/article/details/52856586,所以我放弃了ServiceStack.Redis,选择了StackExchange.Redis,StackExchange.Redis也是开源的,这是地址:https://github.com/StackExchange/StackExchange.Redis,我使用的是.net 4.5,工具采用 vs2015, StackExchange.Redis版本是1.0.488。
对于与Redis连接的配置写法很简单,最简单的写法写个IP和端口就可以了,如你有其他想法自己去查资料吧。StackExchange.Redis中的核心是ConnectionMultiplexer,没事好研究研究。这里我只封装了对缓存的操作,以后可能会更新其他的。
先说说我的想法:
1.定义ICache接口。
2.Redis类和Memcached类,以后想用那个缓存修改一下配置就可以了,非常方便。
3.CacheHelper的实现。
上代码:
ICache.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Common { public interface ICache { /// <summary> /// 缓存过期时间 /// </summary> int TimeOut { set; get; } /// <summary> /// 获得指定键的缓存值 /// </summary> /// <param name="key">缓存键</param> /// <returns>缓存值</returns> object Get(string key); /// <summary> /// 获得指定键的缓存值 /// </summary> T Get<T>(string key); /// <summary> /// 从缓存中移除指定键的缓存值 /// </summary> /// <param name="key">缓存键</param> void Remove(string key); /// <summary> /// 清空所有缓存对象 /// </summary> //void Clear(); /// <summary> /// 将指定键的对象添加到缓存中 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> void Insert(string key, object data); /// <summary> /// 将指定键的对象添加到缓存中 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> void Insert<T>(string key, T data); /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间(秒钟)</param> void Insert(string key, object data, int cacheTime); /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间(秒钟)</param> void Insert<T>(string key, T data, int cacheTime); /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间</param> void Insert(string key, object data, DateTime cacheTime); /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间</param> void Insert<T>(string key, T data, DateTime cacheTime); /// <summary> /// 判断key是否存在 /// </summary> bool Exists(string key); } }
Redis.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 Common { public class Redis : ICache { int Default_Timeout = 600;//默认超时时间(单位秒) string address; JsonSerializerSettings jsonConfig = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore }; ConnectionMultiplexer connectionMultiplexer; IDatabase database; class CacheObject<T> { public int ExpireTime { get; set; } public bool ForceOutofDate { get; set; } public T Value { get; set; } } public Redis() { this.address = ConfigurationManager.AppSettings["RedisServer"]; if (this.address == null || string.IsNullOrWhiteSpace(this.address.ToString())) throw new ApplicationException("配置文件中未找到RedisServer的有效配置"); connectionMultiplexer = ConnectionMultiplexer.Connect(address); database = connectionMultiplexer.GetDatabase(); } /// <summary> /// 连接超时设置 /// </summary> public int TimeOut { get { return Default_Timeout; } set { Default_Timeout = value; } } public object Get(string key) { return Get<object>(key); } public T Get<T>(string key) { DateTime begin = DateTime.Now; var cacheValue = database.StringGet(key); DateTime endCache = DateTime.Now; var value = default(T); if (!cacheValue.IsNull) { var cacheObject = JsonConvert.DeserializeObject<CacheObject<T>>(cacheValue, jsonConfig); if (!cacheObject.ForceOutofDate) database.KeyExpire(key, new TimeSpan(0, 0, cacheObject.ExpireTime)); value = cacheObject.Value; } DateTime endJson = DateTime.Now; return value; } public void Insert(string key, object data) { var jsonData = GetJsonData(data, TimeOut, false); database.StringSet(key, jsonData); } public void Insert(string key, object data, int cacheTime) { var timeSpan = TimeSpan.FromSeconds(cacheTime); var jsonData = GetJsonData(data, TimeOut, true); database.StringSet(key, jsonData, timeSpan); } public void Insert(string key, object data, DateTime cacheTime) { var timeSpan = cacheTime - DateTime.Now; var jsonData = GetJsonData(data, TimeOut, true); database.StringSet(key, jsonData, timeSpan); } public void Insert<T>(string key, T data) { var jsonData = GetJsonData<T>(data, TimeOut, false); database.StringSet(key, jsonData); } public void Insert<T>(string key, T data, int cacheTime) { var timeSpan = TimeSpan.FromSeconds(cacheTime); var jsonData = GetJsonData<T>(data, TimeOut, true); database.StringSet(key, jsonData, timeSpan); } public void Insert<T>(string key, T data, DateTime cacheTime) { var timeSpan = cacheTime - DateTime.Now; var jsonData = GetJsonData<T>(data, TimeOut, true); database.StringSet(key, jsonData, timeSpan); } string GetJsonData(object data, int cacheTime, bool forceOutOfDate) { var cacheObject = new CacheObject<object>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate }; return JsonConvert.SerializeObject(cacheObject, jsonConfig);//序列化对象 } string GetJsonData<T>(T data, int cacheTime, bool forceOutOfDate) { var cacheObject = new CacheObject<T>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate }; return JsonConvert.SerializeObject(cacheObject, jsonConfig);//序列化对象 } /// <summary> /// 删除 /// </summary> /// <param name="key"></param> public void Remove(string key) { database.KeyDelete(key, CommandFlags.HighPriority); } /// <summary> /// 判断key是否存在 /// </summary> public bool Exists(string key) { return database.KeyExists(key); } } }
CacheHelper.cs
using System; using System.Collections.Generic; namespace Common { /// <summary> /// 缓存 /// </summary> public static class Cache { private static object cacheLocker = new object();//缓存锁对象 private static ICache cache = null;//缓存接口 static Cache() { Load(); } /// <summary> /// 加载缓存 /// </summary> /// <exception cref=""></exception> private static void Load() { try { cache = new Redis(); } catch (Exception ex) { //Log.Error(ex.Message); } } public static ICache GetCache() { return cache; } /// <summary> /// 缓存过期时间 /// </summary> public static int TimeOut { get { return cache.TimeOut; } set { lock (cacheLocker) { cache.TimeOut = value; } } } /// <summary> /// 获得指定键的缓存值 /// </summary> /// <param name="key">缓存键</param> /// <returns>缓存值</returns> public static object Get(string key) { if (string.IsNullOrWhiteSpace(key)) return null; return cache.Get(key); } /// <summary> /// 获得指定键的缓存值 /// </summary> /// <param name="key">缓存键</param> /// <returns>缓存值</returns> public static T Get<T>(string key) { return cache.Get<T>(key); } /// <summary> /// 将指定键的对象添加到缓存中 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> public static void Insert(string key, object data) { if (string.IsNullOrWhiteSpace(key) || data == null) return; //lock (cacheLocker) { cache.Insert(key, data); } } /// <summary> /// 将指定键的对象添加到缓存中 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> public static void Insert<T>(string key, T data) { if (string.IsNullOrWhiteSpace(key) || data == null) return; //lock (cacheLocker) { cache.Insert<T>(key, data); } } /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间(分钟)</param> public static void Insert(string key, object data, int cacheTime) { if (!string.IsNullOrWhiteSpace(key) && data != null) { //lock (cacheLocker) { cache.Insert(key, data, cacheTime); } } } /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间(分钟)</param> public static void Insert<T>(string key, T data, int cacheTime) { if (!string.IsNullOrWhiteSpace(key) && data != null) { //lock (cacheLocker) { cache.Insert<T>(key, data, cacheTime); } } } /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间</param> public static void Insert(string key, object data, DateTime cacheTime) { if (!string.IsNullOrWhiteSpace(key) && data != null) { //lock (cacheLocker) { cache.Insert(key, data, cacheTime); } } } /// <summary> /// 将指定键的对象添加到缓存中,并指定过期时间 /// </summary> /// <param name="key">缓存键</param> /// <param name="data">缓存值</param> /// <param name="cacheTime">缓存过期时间</param> public static void Insert<T>(string key, T data, DateTime cacheTime) { if (!string.IsNullOrWhiteSpace(key) && data != null) { //lock (cacheLocker) { cache.Insert<T>(key, data, cacheTime); } } } /// <summary> /// 从缓存中移除指定键的缓存值 /// </summary> /// <param name="key">缓存键</param> public static void Remove(string key) { if (string.IsNullOrWhiteSpace(key)) return; lock (cacheLocker) { cache.Remove(key); } } /// <summary> /// 判断key是否存在 /// </summary> public static bool Exists(string key) { return cache.Exists(key); } } }