Redis作为缓存服务器

 

  1、ICache的Redis实现没有放在'Framework.Cache/Logic'中。如果是以前,我会认为这样不好。我会这样做,'Framework.Cache'项目引用Redis项目或直接从Nuget安装Redis,

把实现定义在‘Framework.Cache/Logic’中,这样结构看起来很顺眼,‘这算是高内聚么!!!’。不过自从接触了IOC后,现在这样的结构似乎也很合理,没什么违和感。

这就好似把‘IRepository’和‘Repositories’,一个放在Domain,一个放在Infrastructure

  2、当前比较稳定的Redis客户端(开源的程序包)有ServiceStack.Redis 和 StackExchange.Redis。我都用了一下,ServiceStatck的

比较好用,不过我感觉后者的性能应该会稍好点

  3、关于ServiceStack.Redis中的接口,IRedisClient,ICacheClient,IRedisTypedClient<T>,IEntityStore<T>,IEntityStore。

这些“乱七八糟”的接口和CRUD都有关系,中的有些方法看似好像是重复的,后续希望能整理出一篇结合源码,理论点的文章

  

一、Framework.Cache

接口ICache,定义缓存操作开放的方法

 1     public interface ICache
 2     {
 3         /// <summary>
 4         /// Gets all entries in the cache
 5         /// </summary>
 6         IEnumerable<KeyValuePair<string, object>> Entries { get; }
 7 
 8         /// <summary>
 9         /// Gets a cache item associated with the specified key or adds the item
10         /// if it doesn't exist in the cache.
11         /// </summary>
12         /// <typeparam name="T">The type of the item to get or add</typeparam>
13         /// <param name="key">The cache item key</param>
14         /// <param name="baseMethod">Func which returns value to be added to the cache</param>
15         /// <returns>Cached item value</returns>
16         T Get<T>(string key, Func<T> baseMethod);
17 
18         /// <summary>
19         /// Gets a cache item associated with the specified key or adds the item
20         /// if it doesn't exist in the cache.
21         /// </summary>
22         /// <typeparam name="T">The type of the item to get or add</typeparam>
23         /// <param name="key">The cache item key</param>
24         /// <param name="baseMethod">Func which returns value to be added to the cache</param>
25         /// <param name="cacheTime">Expiration time in minutes</param>
26         /// <returns>Cached item value</returns>
27         T Get<T>(string key, Func<T> baseMethod, int cacheTime);
28 
29         /// <summary>
30         /// Gets a value indicating whether an item associated with the specified key exists in the cache
31         /// </summary>
32         /// <param name="key">key</param>
33         /// <returns>Result</returns>
34         bool Contains(string key);
35 
36         /// <summary>
37         /// Removes the value with the specified key from the cache
38         /// </summary>
39         /// <param name="key">/key</param>
40         void Remove(string key);
41     }

 

二、基于‘ServiceStack.Redis’的缓存实现

 1 public class SSRedisCache : ICache
 2     {
 3         private const string REGION_NAME = "$#SSRedisCache#$";
 4         private const int _DefaultCacheTime = 30;
 5         private readonly static object s_lock = new object();
 6 
 7         private IRedisClient GetClient()
 8         {
 9             return RedisManager.GetClient();
10         }
11 
12         private IRedisClient GetReadOnlyClient()
13         {
14             return RedisManager.GetReadOnlyClient();
15         }
16 
17         public IEnumerable<KeyValuePair<string, object>> Entries
18         {
19             get { throw new NotImplementedException(); }
20         }
21 
22         public T Get<T>(string key, Func<T> baseMethod)
23         {
24             return Get<T>(key, baseMethod, _DefaultCacheTime);
25         }
26 
27         public T Get<T>(string key, Func<T> baseMethod, int cacheTime)
28         {
29             using (var redisClient = GetClient())
30             {
31                 key = BuildKey(key);
32 
33                 if (redisClient.ContainsKey(key))
34                 {
35                     return redisClient.Get<T>(key);
36                 }
37                 else
38                 {
39                     lock (s_lock)
40                     {
41                         if (!redisClient.ContainsKey(key))
42                         {
43                             var value = baseMethod();
44                             if (value != null) //请区别null与String.Empty
45                             {
46                                 redisClient.Set<T>(key, value, TimeSpan.FromMinutes(cacheTime));
47                                 //redisClient.Save();
48                             }
49                             return value;
50                         }
51                         return redisClient.Get<T>(key);
52                     }
53                 }
54             }
55         }
56 
57         public bool Contains(string key)
58         {
59             using (var redisClient = GetReadOnlyClient())
60             {
61                 return redisClient.ContainsKey(BuildKey(key));
62             }
63         }
64 
65         public void Remove(string key)
66         {
67             using (var redisClient = GetClient())
68             {
69                 redisClient.Remove(BuildKey(key));
70             }
71         }
72 
73         private string BuildKey(string key)
74         {
75             return string.IsNullOrEmpty(key) ? null : REGION_NAME + key;
76         }
77 
78     }

 

三、基于‘StackExchange.Redis’的缓存实现

1 <?xml version="1.0" encoding="utf-8"?>
2 <packages>
3   <package id="MsgPack.Cli" version="0.6.8" targetFramework="net45" />
4   <package id="StackExchange.Redis" version="1.0.488" targetFramework="net45" />
5   <package id="StackExchange.Redis.Extensions.Core" version="1.3.2.0" targetFramework="net45" />
6   <package id="StackExchange.Redis.Extensions.MsgPack" version="1.3.2.0" targetFramework="net45" />
7 </packages>
 1 public class SERedisCache : ICache
 2     {
 3         private const string REGION_NAME = "$#SERedisCache#$";
 4         private const int _DefaultCacheTime = 30;
 5         private readonly static object s_lock = new object();
 6 
 7         private StackExchangeRedisCacheClient GetClient()
 8         {
 9             return new StackExchangeRedisCacheClient(RedisServer.Connection, new MsgPackObjectSerializer());
10         }
11 
12         public IEnumerable<KeyValuePair<string, object>> Entries
13         {
14             get { throw new NotImplementedException(); }
15         }
16 
17         public T Get<T>(string key, Func<T> baseMethod)
18         {
19             return Get(key, baseMethod, _DefaultCacheTime);
20         }
21 
22         public T Get<T>(string key, Func<T> baseMethod, int cacheTime)
23         {
24             using (var cacheClient = GetClient())
25             {
26                 key = BuildKey(key);
27 
28                 if (cacheClient.Exists(key))
29                 {
30                     return cacheClient.Get<T>(key);
31                 }
32                 else
33                 {
34                     lock (s_lock)
35                     {
36                         if (!cacheClient.Exists(key))
37                         {
38                             var value = baseMethod();
39                             if (value != null) //请区别null与String.Empty
40                             {
41                                 cacheClient.Add<T>(key, value, TimeSpan.FromMinutes(cacheTime));
42                             }
43                             return value;
44                         }
45                         return cacheClient.Get<T>(key);
46                     }
47                 }
48             }
49         }
50 
51         public bool Contains(string key)
52         {
53             using (var cacheClient = GetClient())
54             {
55                 return cacheClient.Exists(BuildKey(key));
56             }
57         }
58 
59         public void Remove(string key)
60         {
61             using (var cacheClient = GetClient())
62             {
63                 cacheClient.Remove(BuildKey(key));
64             }
65         }
66 
67         private string BuildKey(string key)
68         {
69             return string.IsNullOrEmpty(key) ? null : REGION_NAME + key;
70         }
71 
72     }

 

完整代码(稍后) 会在另一篇文章关于Web API中附上

 

posted @ 2016-04-28 09:02  Frozen.Zhang  阅读(3403)  评论(0编辑  收藏  举报