Redis缓存、MemCached和.Net内部缓存的切换使用
接口文件:IDataCache.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Untitls.Common { public interface IDataCache { /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">缓存key</param> /// <returns></returns> T Get<T>(string key); T Get<T>(string key,string depFile); /// <summary> /// 写入缓存 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">缓存key</param> /// <param name="value">缓存值</param> /// <returns>返回值,表示:是否写入成功</returns> bool Set<T>(string key, T value); /// <summary> /// 写入缓存,设置过期时间点 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">缓存key</param> /// <param name="value">缓存值</param> /// <param name="expiresAt">过期时间点</param> /// <returns>返回值,表示:是否写入成功</returns> bool Set<T>(string key, T value, DateTime expiresAt); /// <summary> /// 写入缓存,设置过期秒数 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">缓存key</param> /// <param name="value">缓存值</param> /// <param name="expiresSecond">过期秒数</param> /// <returns>返回值,表示:是否写入成功</returns> bool Set<T>(string key, T value, int expiresSecond); bool Set<T>(string key, T value, string depFile); /// <summary> /// 删除缓存 /// </summary> /// <param name="key">缓存key</param> /// <returns></returns> int Delete(string key); /// <summary> /// 删除多个缓存 /// </summary> /// <param name="keys">缓存key数组</param> /// <returns></returns> int Delete(string[] keys); } }
Reids实现文件:RedisCache.cs 注意 要改造成使用PooledRedisClientManager
using ServiceStack.Redis; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace Untitls.Common { /// <summary> /// Redis缓存服务器 /// 服务器和客户端下载: /// https://github.com/MSOpenTech/redis/releases /// https://github.com/ServiceStack/ServiceStack.Redis /// </summary> public class RedisCache : IDataCache { private static RedisClient _redis = null; public static RedisClient redis { get { if (_redis == null) _redis = new RedisClient("192.168.9.128", 6379);//要开启服务器才能连接 return _redis; } } ~RedisCache() { //if (_redis != null) _redis.Shutdown(); } /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T">类型(对象必须可序列化,否则可以作为object类型取出再类型转换,不然会报错)</typeparam> /// <param name="key">缓存key</param> /// <returns></returns> public T Get<T>(string key) { return redis.Get<T>(key); } public T Get<T>(string key, string depFile) { string timeKey = key + "_time"; if (redis.Exists(timeKey) > 0 && redis.Exists(key) > 0) { DateTime obj_time = Get<DateTime>(timeKey); T obj_cache = Get<T>(key); if (File.Exists(depFile)) { FileInfo fi = new FileInfo(depFile); if (obj_time != fi.LastWriteTime) { Delete(key); Delete(timeKey); return default(T); } else return obj_cache; } else { throw new Exception("文件(" + depFile + ")不存在!"); } } else return default(T); } public bool Set<T>(string key, T value) { return redis.Set<T>(key, value); } public bool Set<T>(string key, T value, DateTime expiresAt) { return redis.Set<T>(key, value, expiresAt); } public bool Set<T>(string key, T value, int expiresSecond) { return redis.Set<T>(key, value, DateTime.Now.AddSeconds(expiresSecond)); } public bool Set<T>(string key, T value, string depFile) { bool ret1 = redis.Set<T>(key, value); if (ret1 && File.Exists(depFile)) { FileInfo fi = new FileInfo(depFile); DateTime lastWriteTime = fi.LastWriteTime; return redis.Set<DateTime>(key + "_time", lastWriteTime); } return false; } public int Delete(string key) { return redis.Del(key); } public int Delete(string[] keys) { return redis.Del(keys); } public void Dispose() { if (_redis != null) _redis.Shutdown();//调用Dispose释放memcached客户端连接 } } }
实现文件:MemcachedCache.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Memcached.ClientLibrary; using System.IO; namespace Untitls.Common { public class MemcachedCache:IDataCache { private MemcachedClient _mc =null; protected MemcachedClient mc { get { if(_mc==null) _mc=new MemcachedClient();//初始化一个客户端 return _mc; } } /// <summary> /// 如果默认不是本地服务,可以额外指定memcached服务器地址 /// </summary> public static string[] serverList { get; set; } private static MemcachedCache _instance = null; /// <summary> /// 单例实例对象,外部只能通过MemcachedHelper.instance使用memcached /// </summary> public static MemcachedCache instance { get { if (_instance == null) { if (serverList != null && serverList.Length > 0) _instance = new MemcachedCache(serverList); else _instance = new MemcachedCache(); } return _instance; } } SockIOPool pool; private void start(params string[]servers) { string[] serverlist; if (servers == null || servers.Length < 1) { serverlist = new string[] { "127.0.0.1:11011" }; //服务器列表,可多个 } else { serverlist=servers; } pool = SockIOPool.GetInstance(); //根据实际情况修改下面参数 pool.SetServers(serverlist); pool.InitConnections = 3; pool.MinConnections = 3; pool.MaxConnections = 5; pool.SocketConnectTimeout = 1000; pool.SocketTimeout = 3000; pool.MaintenanceSleep = 30; pool.Failover = true; pool.Nagle = false; pool.Initialize(); // initialize the pool for memcache servers } public MemcachedCache(string[] servers) { start(servers); } public MemcachedCache() { start(); } ~MemcachedCache() { //if (pool != null) pool.Shutdown(); } public T Get<T>(string key) { object data = mc.Get(key); if (data is T) return (T)data; else return default(T); } public T Get<T>(string key, string depFile) { string timeKey = key + "_time"; if (mc.KeyExists(timeKey) && mc.KeyExists(key)) { DateTime obj_time = Get<DateTime>(timeKey); T obj_cache = Get<T>(key); if (File.Exists(depFile)) { FileInfo fi = new FileInfo(depFile); if (obj_time != fi.LastWriteTime) { Delete(key); Delete(timeKey); return default(T); } else return obj_cache; } else { throw new Exception("文件(" + depFile + ")不存在!"); } } else return default(T); } public bool Set<T>(string key, T value) { return mc.Set(key, value); } public bool Set<T>(string key, T value, DateTime expiresAt) { return mc.Set(key, value, expiresAt); } public bool Set<T>(string key, T value, int expiresSecond) { return mc.Set(key, value, DateTime.Now.AddSeconds(expiresSecond)); } public bool Set<T>(string key, T value, string depFile) { bool ret1 = mc.Set(key, value); if (ret1 && File.Exists(depFile)) { FileInfo fi = new FileInfo(depFile); DateTime lastWriteTime = fi.LastWriteTime; return mc.Set(key + "_time", lastWriteTime); } return false; } public int Delete(string key) { return mc.Delete(key)?1:0; } public int Delete(string[] keys) { int i = 0; foreach (var key in keys) { mc.Delete(key); i++; } return i; } //在应用程序退出之前,调用Dispose释放memcached客户端连接 public void Dispose() { if (pool != null) pool.Shutdown(); } } }
实现文件:RuntimeCache.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Web; using System.Web.Caching; namespace Untitls.Common { public class RuntimeCache : IDataCache { #region 删除缓存 /// <summary> /// 删除缓存 /// </summary> /// <param name="CacheKey">键</param> public int Delete(string CacheKey) { HttpRuntime.Cache.Remove(CacheKey); return 1; } public int Delete(string[] CacheKeys) { int i = 0; foreach (var key in CacheKeys) { HttpRuntime.Cache.Remove(key); i++; } return i; } #endregion #region 获取缓存,依赖时间 /// <summary> /// 获取缓存,依赖时间 /// </summary> /// <param name="CacheKey">键</param> /// <returns></returns> public T Get<T>(string CacheKey) { object obj_time = HttpRuntime.Cache[CacheKey + "_time"]; object obj_cache = HttpRuntime.Cache[CacheKey]; if (obj_time != null && obj_cache != null) { if (Convert.ToDateTime(obj_time) < DateTime.Now) { Delete(CacheKey); Delete(CacheKey + "_time"); return default(T); } else return (T)obj_cache; } else { Delete(CacheKey); Delete(CacheKey + "_time"); return default(T); } } #endregion #region 获取缓存,依赖文件 /// <summary> /// 获取缓存,依赖文件 /// </summary> /// <param name="CacheKey">键</param> /// <param name="depFile">依赖的文件</param> /// <returns></returns> public T Get<T>(string CacheKey, string depFile) { object obj_time = HttpRuntime.Cache[CacheKey + "_time"]; object obj_cache = HttpRuntime.Cache[CacheKey]; if (File.Exists(depFile)) { FileInfo fi = new FileInfo(depFile); if (obj_time != null && obj_cache != null) { if (Convert.ToDateTime(obj_time) != fi.LastWriteTime) { Delete(CacheKey); Delete(CacheKey + "_time"); return default(T); } else return (T)obj_cache; } else { Delete(CacheKey); Delete(CacheKey + "_time"); return default(T); } } else { throw new Exception("文件(" + depFile + ")不存在!"); } } #endregion #region 简单的插入缓存 /// <summary> /// 简单的插入缓存 /// </summary> /// <param name="CacheKey">键</param> /// <param name="objObject">数据</param> public bool Set<T>(string CacheKey, T objObject) { HttpRuntime.Cache.Insert(CacheKey, objObject); return true; } #endregion #region 有过期时间的插入缓存数据 public bool Set<T>(string CacheKey, T objObject, DateTime expiresAt) { HttpRuntime.Cache.Insert(CacheKey, objObject, null, expiresAt, Cache.NoSlidingExpiration); HttpRuntime.Cache.Insert(CacheKey + "_time", expiresAt, null, expiresAt, Cache.NoSlidingExpiration);//存储过期时间 return true; } #endregion #region 插入缓存数据,指定缓存多少秒 public bool Set<T>(string CacheKey, T objObject, int seconds) { DateTime expiresAt = DateTime.Now.AddSeconds(seconds); HttpRuntime.Cache.Insert(CacheKey, objObject, null, expiresAt, Cache.NoSlidingExpiration); HttpRuntime.Cache.Insert(CacheKey + "_time", expiresAt, null, expiresAt, Cache.NoSlidingExpiration);//存储过期时间 return true; } #endregion #region 依赖文件的缓存,文件没改不会过期 /// <summary> /// 依赖文件的缓存,文件没改不会过期 /// </summary> /// <param name="CacheKey">键</param> /// <param name="objObject">数据</param> /// <param name="depfilename">依赖文件,可调用 DataCache 里的变量</param> public bool Set<T>(string CacheKey, T objObject, string depfilename) { //缓存依赖对象 System.Web.Caching.CacheDependency dep = new System.Web.Caching.CacheDependency(depfilename); DateTime absoluteExpiration = System.Web.Caching.Cache.NoAbsoluteExpiration; TimeSpan slidingExpiration = System.Web.Caching.Cache.NoSlidingExpiration; System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert( CacheKey, objObject, dep, absoluteExpiration, //从不过期 slidingExpiration, //禁用可调过期 System.Web.Caching.CacheItemPriority.Default, null); if (File.Exists(depfilename)) { FileInfo fi = new FileInfo(depfilename); DateTime lastWriteTime = fi.LastWriteTime; HttpRuntime.Cache.Insert(CacheKey + "_time", lastWriteTime, null, absoluteExpiration, slidingExpiration);//存储文件最后修改时间 } return true; } #endregion } }
缓存统一入口
public partial class DataCache { private static IDataCache _instance = null; /// <summary> /// 静态实例,外部可直接调用 /// </summary> public static IDataCache Instance { get { if (_instance == null) _instance = new RuntimeCache();//这里可以改变缓存类型 return _instance; } } }
缓存在分布式应用中有很多好处,大家可以合理利用。