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中附上

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM