程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 一個技術汪的開源夢 —— 公共組件緩存之分布式緩存 Redis 實現篇,redis

一個技術汪的開源夢 —— 公共組件緩存之分布式緩存 Redis 實現篇,redis

編輯:關於.NET

一個技術汪的開源夢 —— 公共組件緩存之分布式緩存 Redis 實現篇,redis


Redis 安裝 & 配置

本測試環境將在 CentOS 7 x64 上安裝最新版本的 Redis。

1. 運行以下命令安裝 Redis

$ wget http://download.redis.io/releases/redis-3.2.6.tar.gz
$ tar xzf redis-3.2.6.tar.gz
$ cd redis-3.2.6
$ make install

如果 CentOS 上提示 wget 命令未找到,則先安裝 net-tools。

yum install net-tools

2. Redis 配置文件

1)開啟守護程序

    修改 daemonize 節點為 yes。

2)運行外部IP訪問

    配置 bind 節點為 0.0.0.0

 

本次示例只使用 Redis 的緩存 所以配置暫時只修改這兩處即可。

3. 設置 Redis 開機自動啟動

 1)在 Redis 的源碼包中找到 utils 目錄

 2) 將 redis_init_script 文件復制到 /etc/init.d 目錄下並重命名為 redisd

cp redis_init_script /etc/init.d/redisd

 3) 打開 redisd 修改部分配置。

 1 #!/bin/sh
 2 # chkconfig:    2345 90 10
 3 # Simple Redis init.d script conceived to work on Linux systems
 4 # as it does use of the /proc filesystem.
 5 
 6 REDISPORT=6379
 7 EXEC=/usr/local/bin/redis-server
 8 CLIEXEC=/usr/local/bin/redis-cli
 9 
10 PIDFILE=/var/run/redis_${REDISPORT}.pid
11 CONF="/etc/redis/redis_${REDISPORT}.conf"

其中第二行 # chkconfig: 2345 90 10 需要另行添加。

- REDISPORT Redis 運行端口號;

- EXEC Redis 服務器命令文件路徑(根據實際情況修改);

- CLIEXEC Redis 客戶端命令文件路徑(亦根據實際情況修改);

- CONF Redis 配置文件。

 

4)設置開機啟動 & 啟動、停止服務

#設置為開機自啟動服務器
chkconfig redisd on
#打開服務
service redisd start
#關閉服務
service redisd stop

 

主:如果外部機器還訪問不到 Redis 服務器,請將 6379 端口號加防火牆例外即可。

 

代碼實現:

Common 包 接口定義 & 分布式緩存實例獲取和配置

- IDistributedCache 接口
 1 using System;
 2 
 3 namespace Wlitsoft.Framework.Common.Core
 4 {
 5     /// <summary>
 6     /// 分布式緩存接口。
 7     /// </summary>
 8     public interface IDistributedCache
 9     {
10         /// <summary>
11         /// 獲取緩存。
12         /// </summary>
13         /// <typeparam name="T">緩存類型。</typeparam>
14         /// <param name="key">緩存鍵值。</param>
15         /// <returns>獲取到的緩存。</returns>
16         T Get<T>(string key);
17 
18         /// <summary>
19         /// 設置緩存。
20         /// </summary>
21         /// <typeparam name="T">緩存類型。</typeparam>
22         /// <param name="key">緩存鍵值。</param>
23         /// <param name="value">要緩存的對象。</param>
24         void Set<T>(string key, T value);
25 
26         /// <summary>
27         /// 設置緩存。
28         /// </summary>
29         /// <typeparam name="T">緩存類型。</typeparam>
30         /// <param name="key">緩存鍵值。</param>
31         /// <param name="value">要緩存的對象。</param>
32         /// <param name="expiredTime">過期時間。</param>
33         void Set<T>(string key, T value, TimeSpan expiredTime);
34 
35         /// <summary>
36         /// 判斷指定鍵值的緩存是否存在。
37         /// </summary>
38         /// <param name="key">緩存鍵值。</param>
39         /// <returns>一個布爾值,表示緩存是否存在。</returns>
40         bool Exists(string key);
41 
42         /// <summary>
43         /// 移除指定鍵值的緩存。
44         /// </summary>
45         /// <param name="key">緩存鍵值。</param>
46         bool Remove(string key);
47 
48         /// <summary>
49         /// 獲取 Hash 表中的緩存。
50         /// </summary>
51         /// <typeparam name="T">緩存類型。</typeparam>
52         /// <param name="key">緩存鍵值。</param>
53         /// <param name="hashField">要獲取的 hash 字段。</param>
54         /// <returns>獲取到的緩存。</returns>
55         T GetHash<T>(string key, string hashField);
56 
57         /// <summary>
58         /// 設置 緩存到 Hash 表。
59         /// </summary>
60         /// <typeparam name="T">緩存類型。</typeparam>
61         /// <param name="key">緩存鍵值。</param>
62         /// <param name="hashField">要設置的 hash 字段。</param>
63         /// <param name="hashValue">要設置的 hash 值。</param>
64         void SetHash<T>(string key, string hashField, T hashValue);
65 
66         /// <summary>
67         /// 判斷指定鍵值的 Hash 緩存是否存在。
68         /// </summary>
69         /// <param name="key">緩存鍵值。</param>
70         /// <param name="hashField">hash 字段。</param>
71         /// <returns>一個布爾值,表示緩存是否存在。</returns>
72         bool ExistsHash(string key, string hashField);
73 
74         /// <summary>
75         /// 刪除 hash 表中的指定字段的緩存。
76         /// </summary>
77         /// <param name="key">緩存鍵值。</param>
78         /// <param name="hashField">hash 字段。</param>
79         /// <returns>一個布爾值,表示緩存是否刪除成功。</returns>
80         bool DeleteHash(string key, string hashField);
81     }
82 }

 - App 類

1 /// <summary>
2 /// 獲取分布式緩存。
3 /// </summary>
4 public static IDistributedCache DistributedCache { get; internal set; }

 - AppBuilder 類

 1 namespace Wlitsoft.Framework.Common
 2 {
 3     /// <summary>
 4     /// 應用 構造。
 5     /// </summary>
 6     public class AppBuilder
 7     {
 8         #region 添加序列化者
 9 
10         /// <summary>
11         /// 添加序列化者。
12         /// </summary>
13         /// <param name="type">序列化類型。</param>
14         /// <param name="serializer">序列化者接口。</param>
15         public void AddSerializer(SerializeType type, ISerializer serializer)
16         {
17             #region 參數校驗
18 
19             if (serializer == null)
20                 throw new ObjectNullException(nameof(serializer));
21 
22             #endregion
23 
24             App.SerializerService.SetSerializer(type, serializer);
25         }
26 
27         #endregion
28 
29         #region 添加日志記錄者
30 
31         /// <summary>
32         /// 添加日志記錄者。
33         /// </summary>
34         /// <param name="name">日志記錄者名稱。</param>
35         /// <param name="logger">日志接口。</param>
36         public void AddLogger(string name, ILog logger)
37         {
38             #region 參數校驗
39 
40             if (string.IsNullOrEmpty(name))
41                 throw new StringNullOrEmptyException(nameof(name));
42 
43             if (logger == null)
44                 throw new ObjectNullException(nameof(logger));
45 
46             #endregion
47 
48             App.LoggerService.SetLogger(name, logger);
49         }
50 
51         #endregion
52 
53         #region 設置分布式緩存
54 
55         /// <summary>
56         /// 設置分布式緩存。
57         /// </summary>
58         /// <param name="cache">分布式緩存實例。</param>
59         /// <returns></returns>
60         public AppBuilder SetDistributedCache(IDistributedCache cache)
61         {
62             #region 參數校驗
63 
64             if (cache == null)
65                 throw new ObjectNullException(nameof(cache));
66 
67             #endregion
68 
69             App.DistributedCache = cache;
70             return this;
71         }
72 
73         #endregion
74     }
75 }

 

分布式緩存 Redis 實現

 - RedisCache 類

  1 using System;
  2 using System.Linq;
  3 using System.Threading;
  4 using StackExchange.Redis;
  5 using Wlitsoft.Framework.Common.Core;
  6 using Wlitsoft.Framework.Common.Extension;
  7 using Wlitsoft.Framework.Common.Exception;
  8 
  9 namespace Wlitsoft.Framework.Caching.Redis
 10 {
 11     /// <summary>
 12     /// Redis 緩存。
 13     /// </summary>
 14     public class RedisCache : IDistributedCache
 15     {
 16         #region 私有屬性
 17 
 18         //redis 連接實例。
 19         private volatile ConnectionMultiplexer _connection;
 20 
 21         //redis 緩存數據庫實例。
 22         private IDatabase _database;
 23 
 24         //連接實例鎖。
 25         private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(1, 1);
 26 
 27         //Redis 配置。
 28         internal static RedisCacheConfiguration RedisCacheConfiguration;
 29 
 30         #endregion
 31 
 32         #region IDistributedCache 成員
 33 
 34         /// <summary>
 35         /// 獲取緩存。
 36         /// </summary>
 37         /// <typeparam name="T">緩存類型。</typeparam>
 38         /// <param name="key">緩存鍵值。</param>
 39         /// <returns>獲取到的緩存。</returns>
 40         public T Get<T>(string key)
 41         {
 42             #region 參數校驗
 43 
 44             if (string.IsNullOrEmpty(key))
 45                 throw new StringNullOrEmptyException(nameof(key));
 46 
 47             #endregion
 48 
 49             this.Connect();
 50             string result = this._database.StringGet(key);
 51             if (string.IsNullOrEmpty(result))
 52                 return default(T);
 53             return result.ToJsonObject<T>();
 54         }
 55 
 56         /// <summary>
 57         /// 設置緩存。
 58         /// </summary>
 59         /// <typeparam name="T">緩存類型。</typeparam>
 60         /// <param name="key">緩存鍵值。</param>
 61         /// <param name="value">要緩存的對象。</param>
 62         public void Set<T>(string key, T value)
 63         {
 64             #region 參數校驗
 65 
 66             if (string.IsNullOrEmpty(key))
 67                 throw new StringNullOrEmptyException(nameof(key));
 68 
 69             if (value == null)
 70                 throw new ObjectNullException(nameof(value));
 71 
 72             #endregion
 73 
 74             this.Connect();
 75             this._database.StringSet(key, value.ToJsonString());
 76         }
 77 
 78         /// <summary>
 79         /// 設置緩存。
 80         /// </summary>
 81         /// <typeparam name="T">緩存類型。</typeparam>
 82         /// <param name="key">緩存鍵值。</param>
 83         /// <param name="value">要緩存的對象。</param>
 84         /// <param name="expiredTime">過期時間。</param>
 85         public void Set<T>(string key, T value, TimeSpan expiredTime)
 86         {
 87             #region 參數校驗
 88 
 89             if (string.IsNullOrEmpty(key))
 90                 throw new StringNullOrEmptyException(nameof(key));
 91 
 92             if (value == null)
 93                 throw new ObjectNullException(nameof(value));
 94 
 95             #endregion
 96 
 97             this.Connect();
 98             this._database.StringSet(key, value.ToJsonString(), expiredTime);
 99         }
100 
101         /// <summary>
102         /// 判斷指定鍵值的緩存是否存在。
103         /// </summary>
104         /// <param name="key">緩存鍵值。</param>
105         /// <returns>一個布爾值,表示緩存是否存在。</returns>
106         public bool Exists(string key)
107         {
108             #region 參數校驗
109 
110             if (string.IsNullOrEmpty(key))
111                 throw new StringNullOrEmptyException(nameof(key));
112 
113             #endregion
114 
115             this.Connect();
116             return this._database.KeyExists(key);
117         }
118 
119         /// <summary>
120         /// 移除指定鍵值的緩存。
121         /// </summary>
122         /// <param name="key">緩存鍵值。</param>
123         public bool Remove(string key)
124         {
125             #region 參數校驗
126 
127             if (string.IsNullOrEmpty(key))
128                 throw new StringNullOrEmptyException(nameof(key));
129 
130             #endregion
131 
132             this.Connect();
133             return this._database.KeyDelete(key);
134         }
135 
136         /// <summary>
137         /// 獲取 Hash 表中的緩存。
138         /// </summary>
139         /// <typeparam name="T">緩存類型。</typeparam>
140         /// <param name="key">緩存鍵值。</param>
141         /// <param name="hashField">要獲取的 hash 字段。</param>
142         /// <returns>獲取到的緩存。</returns>
143         public T GetHash<T>(string key, string hashField)
144         {
145             #region 參數校驗
146 
147             if (string.IsNullOrEmpty(key))
148                 throw new StringNullOrEmptyException(nameof(key));
149 
150             if (string.IsNullOrEmpty(hashField))
151                 throw new StringNullOrEmptyException(nameof(hashField));
152 
153             #endregion
154 
155             this.Connect();
156             string value = this._database.HashGet(key, hashField);
157             if (string.IsNullOrEmpty(value))
158                 return default(T);
159             return value.ToJsonObject<T>();
160         }
161 
162         /// <summary>
163         /// 設置 緩存到 Hash 表。
164         /// </summary>
165         /// <typeparam name="T">緩存類型。</typeparam>
166         /// <param name="key">緩存鍵值。</param>
167         /// <param name="hashField">要設置的 hash 字段。</param>
168         /// <param name="hashValue">要設置的 hash 值。</param>
169         public void SetHash<T>(string key, string hashField, T hashValue)
170         {
171             #region 參數校驗
172 
173             if (string.IsNullOrEmpty(key))
174                 throw new StringNullOrEmptyException(nameof(key));
175 
176             if (string.IsNullOrEmpty(hashField))
177                 throw new StringNullOrEmptyException(nameof(hashField));
178 
179             if (hashValue == null)
180                 throw new ObjectNullException(nameof(hashValue));
181 
182             #endregion
183 
184             this.Connect();
185             this._database.HashSet(key, hashField, hashValue.ToJsonString());
186         }
187 
188         /// <summary>
189         /// 判斷指定鍵值的 Hash 緩存是否存在。
190         /// </summary>
191         /// <param name="key">緩存鍵值。</param>
192         /// <param name="hashField">hash 字段。</param>
193         /// <returns>一個布爾值,表示緩存是否存在。</returns>
194         public bool ExistsHash(string key, string hashField)
195         {
196             #region 參數校驗
197 
198             if (string.IsNullOrEmpty(key))
199                 throw new StringNullOrEmptyException(nameof(key));
200 
201             if (string.IsNullOrEmpty(hashField))
202                 throw new StringNullOrEmptyException(nameof(hashField));
203 
204             #endregion
205 
206             this.Connect();
207             return this._database.HashExists(key, hashField);
208         }
209 
210         /// <summary>
211         /// 刪除 hash 表中的指定字段的緩存。
212         /// </summary>
213         /// <param name="key">緩存鍵值。</param>
214         /// <param name="hashField">hash 字段。</param>
215         /// <returns>一個布爾值,表示緩存是否刪除成功。</returns>
216         public bool DeleteHash(string key, string hashField)
217         {
218             #region 參數校驗
219 
220             if (string.IsNullOrEmpty(key))
221                 throw new StringNullOrEmptyException(nameof(key));
222 
223             if (string.IsNullOrEmpty(hashField))
224                 throw new StringNullOrEmptyException(nameof(hashField));
225 
226             #endregion
227 
228             this.Connect();
229             return this._database.HashDelete(key, hashField);
230         }
231 
232         #endregion
233 
234         #region 私有方法
235 
236         /// <summary>
237         /// 連接。
238         /// </summary>
239         private void Connect()
240         {
241             if (this._connection != null)
242                 return;
243 
244             this._connectionLock.Wait();
245             try
246             {
247                 if (this._connection == null)
248                 {
249                     this._connection = ConnectionMultiplexer.Connect(this.GetConfigurationOptions());
250                     this._database = this._connection.GetDatabase();
251                 }
252             }
253             finally
254             {
255                 this._connectionLock.Release();
256             }
257         }
258 
259         private ConfigurationOptions GetConfigurationOptions()
260         {
261             #region 校驗
262 
263             if (RedisCacheConfiguration == null)
264                 throw new ObjectNullException(nameof(RedisCacheConfiguration));
265 
266             if (!RedisCacheConfiguration.HostAndPoints.Any())
267                 throw new Exception("RedisCahce 的 HostAndPoints 不能為空");
268 
269             #endregion
270 
271             ConfigurationOptions options = new ConfigurationOptions();
272 
273             foreach (string item in RedisCacheConfiguration.HostAndPoints)
274                 options.EndPoints.Add(item);
275 
276             options.ConnectRetry = RedisCacheConfiguration.ConnectRetry;
277             options.ConnectTimeout = RedisCacheConfiguration.ConnectTimeout;
278 
279             return options;
280         }
281 
282         #endregion
283 
284         #region 析構函數
285 
286         /// <summary>
287         /// 析構 <see cref="RedisCache"/> 類型的對象。
288         /// </summary>
289         ~RedisCache()
290         {
291             _connection?.Close();
292         }
293 
294         #endregion
295     }
296 }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved