Memcach、WebCache、MemoryCache缓存帮助类

@TOC

场景说明

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

使用方法

1
2
3
4
5
6
7
8
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覆盖缓存,这种错误虽然少,但一出现就很难排查。这里用的是简单单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

规范化缓存封装的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
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 的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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 的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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; }
}
}

原文链接:/2020-07-03-forcache.html

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

撸代码不易,给点物质上的支持吧~

支付宝
微信