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; }
}
}