StackExchange.Redis學習筆記(一) Redis的使用初探


Redis

  • Redis將其數據庫完全保存在內存中,僅使用磁盤進行持久化。
  • 與其它鍵值數據存儲相比,Redis有一組相對豐富的數據類型。
  • Redis可以將數據復制到任意數量的從機中

Redis的安裝

  官網只提供了linux的安裝包,我win10 的系統,在github上下載的windows安裝包 3.0.504最新穩定版的

  github地址:https://github.com/MicrosoftArchive/redis/releases   
  官網下載地址:https://redis.io/download   

  將壓縮包解壓到文件夾后,雙擊“redis-server.exe”即可啟動redis服務,也可以在環境變量中配置之后,用redis-server 命令來開啟服務,以下是服務啟動成功界面

  

Redis的使用

  C#可選用ServiceStack.Redis或者StackExchange.Redis等客戶端程序操作redis,由於ServiceStack.Redis已經收費了,我這里用的是StackExchange.Redis,通過Nuget安裝到項目中

接下來我們創建一個操作redis的幫助類:

  1    public static class StackExchangeRedisHelper
  2     {
  3         private static readonly string Coonstr = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString;//
  4         private static object _locker = new Object();
  5         private static ConnectionMultiplexer _instance = null;
  6         /// <summary>
  7         /// 使用一個靜態屬性來返回已連接的實例,如下列中所示。這樣,一旦 ConnectionMultiplexer 斷開連接,便可以初始化新的連接實例。
  8         /// </summary>
  9         public static ConnectionMultiplexer Instance
 10         {
 11             get
 12             {
 13                 if (_instance == null)
 14                 {
 15                     lock (_locker)
 16                     {
 17                         if (_instance == null || !_instance.IsConnected)
 18                         {
 19                             _instance = ConnectionMultiplexer.Connect(Coonstr);
 20                         }
 21                     }
 22                 }
 23                 //注冊如下事件
 24                 _instance.ConnectionFailed += MuxerConnectionFailed;
 25                 _instance.ConnectionRestored += MuxerConnectionRestored;
 26                 _instance.ErrorMessage += MuxerErrorMessage;
 27                 _instance.ConfigurationChanged += MuxerConfigurationChanged;
 28                 _instance.HashSlotMoved += MuxerHashSlotMoved;
 29                 _instance.InternalError += MuxerInternalError;
 30                 return _instance;
 31             }
 32         }
 33 
 34 
 35         static StackExchangeRedisHelper()
 36         {
 37         }
 38 
 39         /// <summary>
 40         /// 
 41         /// </summary>
 42         /// <returns></returns>
 43         public static IDatabase GetDatabase()
 44         {
 45             return Instance.GetDatabase();
 46         }
 47 
 48         /// <summary>
 49         /// 這里的 MergeKey 用來拼接 Key 的前綴,具體不同的業務模塊使用不同的前綴。
 50         /// </summary>
 51         /// <param name="key"></param>
 52         /// <returns></returns>
 53         private static string MergeKey(string key)
 54         {
 55             return BaseSystemInfo.SystemCode + key;
 56         }
 57         /// <summary>
 58         /// 根據key獲取緩存對象
 59         /// </summary>
 60         /// <typeparam name="T"></typeparam>
 61         /// <param name="key"></param>
 62         /// <returns></returns>
 63         public static T Get<T>(string key)
 64         {
 65             key = MergeKey(key);
 66             return Deserialize<T>(GetDatabase().StringGet(key));
 67         }
 68         /// <summary>
 69         /// 根據key獲取緩存對象
 70         /// </summary>
 71         /// <param name="key"></param>
 72         /// <returns></returns>
 73         public static object Get(string key)
 74         {
 75             key = MergeKey(key);
 76             return Deserialize<object>(GetDatabase().StringGet(key));
 77         }
 78 
 79         /// <summary>
 80         /// 設置緩存
 81         /// </summary>
 82         /// <param name="key"></param>
 83         /// <param name="value"></param>
 84         public static void Set(string key, object value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags flags = CommandFlags.None)
 85         {
 86             key = MergeKey(key);
 87             GetDatabase().StringSet(key, Serialize(value), expiry, when, flags);
 88         }
 89 
 90         /// <summary>
 91         /// 判斷在緩存中是否存在該key的緩存數據
 92         /// </summary>
 93         /// <param name="key"></param>
 94         /// <returns></returns>
 95         public static bool Exists(string key)
 96         {
 97             key = MergeKey(key);
 98             return GetDatabase().KeyExists(key);  //可直接調用
 99         }
100 
101         /// <summary>
102         /// 移除指定key的緩存
103         /// </summary>
104         /// <param name="key"></param>
105         /// <returns></returns>
106         public static bool Remove(string key)
107         {
108             key = MergeKey(key);
109             return GetDatabase().KeyDelete(key);
110         }
111 
112         /// <summary>
113         /// 異步設置
114         /// </summary>
115         /// <param name="key"></param>
116         /// <param name="value"></param>
117         public static async Task SetAsync(string key, object value)
118         {
119             key = MergeKey(key);
120             await GetDatabase().StringSetAsync(key, Serialize(value));
121         }
122 
123         /// <summary>
124         /// 根據key獲取緩存對象
125         /// </summary>
126         /// <param name="key"></param>
127         /// <returns></returns>
128         public static async Task<object> GetAsync(string key)
129         {
130             key = MergeKey(key);
131             object value = await GetDatabase().StringGetAsync(key);
132             return value;
133         }
134 
135         /// <summary>
136         /// 實現遞增
137         /// </summary>
138         /// <param name="key"></param>
139         /// <returns></returns>
140         public static long Increment(string key)
141         {
142             key = MergeKey(key);
143             //三種命令模式
144             //Sync,同步模式會直接阻塞調用者,但是顯然不會阻塞其他線程。
145             //Async,異步模式直接走的是Task模型。
146             //Fire - and - Forget,就是發送命令,然后完全不關心最終什么時候完成命令操作。
147             //即發即棄:通過配置 CommandFlags 來實現即發即棄功能,在該實例中該方法會立即返回,如果是string則返回null 如果是int則返回0.這個操作將會繼續在后台運行,一個典型的用法頁面計數器的實現:
148             return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
149         }
150 
151         /// <summary>
152         /// 實現遞減
153         /// </summary>
154         /// <param name="key"></param>
155         /// <param name="value"></param>
156         /// <returns></returns>
157         public static long Decrement(string key, string value)
158         {
159             key = MergeKey(key);
160             return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget);
161         }
162 
163         /// <summary>
164         /// 序列化對象
165         /// </summary>
166         /// <param name="o"></param>
167         /// <returns></returns>
168         static byte[] Serialize(object o)
169         {
170             if (o == null)
171             {
172                 return null;
173             }
174             BinaryFormatter binaryFormatter = new BinaryFormatter();
175             using (MemoryStream memoryStream = new MemoryStream())
176             {
177                 binaryFormatter.Serialize(memoryStream, o);
178                 byte[] objectDataAsStream = memoryStream.ToArray();
179                 return objectDataAsStream;
180             }
181         }
182 
183         /// <summary>
184         /// 反序列化對象
185         /// </summary>
186         /// <typeparam name="T"></typeparam>
187         /// <param name="stream"></param>
188         /// <returns></returns>
189         static T Deserialize<T>(byte[] stream)
190         {
191             if (stream == null)
192             {
193                 return default(T);
194             }
195             BinaryFormatter binaryFormatter = new BinaryFormatter();
196             using (MemoryStream memoryStream = new MemoryStream(stream))
197             {
198                 T result = (T)binaryFormatter.Deserialize(memoryStream);
199                 return result;
200             }
201         }
202         /// <summary>
203         /// 配置更改時
204         /// </summary>
205         /// <param name="sender"></param>
206         /// <param name="e"></param>
207         private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
208         {
209             LogHelper.WriteInfoLog("Configuration changed: " + e.EndPoint);
210         }
211         /// <summary>
212         /// 發生錯誤時
213         /// </summary>
214         /// <param name="sender"></param>
215         /// <param name="e"></param>
216         private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
217         {
218             LogHelper.WriteInfoLog("ErrorMessage: " + e.Message);
219         }
220         /// <summary>
221         /// 重新建立連接之前的錯誤
222         /// </summary>
223         /// <param name="sender"></param>
224         /// <param name="e"></param>
225         private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
226         {
227             LogHelper.WriteInfoLog("ConnectionRestored: " + e.EndPoint);
228         }
229         /// <summary>
230         /// 連接失敗 , 如果重新連接成功你將不會收到這個通知
231         /// </summary>
232         /// <param name="sender"></param>
233         /// <param name="e"></param>
234         private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
235         {
236             LogHelper.WriteInfoLog("重新連接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
237         }
238         /// <summary>
239         /// 更改集群
240         /// </summary>
241         /// <param name="sender"></param>
242         /// <param name="e"></param>
243         private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
244         {
245             LogHelper.WriteInfoLog("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
246         }
247         /// <summary>
248         /// redis類庫錯誤
249         /// </summary>
250         /// <param name="sender"></param>
251         /// <param name="e"></param>
252         private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
253         {
254             LogHelper.WriteInfoLog("InternalError:Message" + e.Exception.Message);
255         }
256 
257         //場景不一樣,選擇的模式便會不一樣,大家可以按照自己系統架構情況合理選擇長連接還是Lazy。
258         //建立連接后,通過調用ConnectionMultiplexer.GetDatabase 方法返回對 Redis Cache 數據庫的引用。從 GetDatabase 方法返回的對象是一個輕量級直通對象,不需要進行存儲。
259 
260         /// <summary>
261         /// 使用的是Lazy,在真正需要連接時創建連接。
262         /// 延遲加載技術
263         /// 微軟azure中的配置 連接模板
264         /// </summary>
265         //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
266         //{
267         //    //var options = ConfigurationOptions.Parse(constr);
268         //    ////options.ClientName = GetAppName(); // only known at runtime
269         //    //options.AllowAdmin = true;
270         //    //return ConnectionMultiplexer.Connect(options);
271         //    ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr);
272         //    muxer.ConnectionFailed += MuxerConnectionFailed;
273         //    muxer.ConnectionRestored += MuxerConnectionRestored;
274         //    muxer.ErrorMessage += MuxerErrorMessage;
275         //    muxer.ConfigurationChanged += MuxerConfigurationChanged;
276         //    muxer.HashSlotMoved += MuxerHashSlotMoved;
277         //    muxer.InternalError += MuxerInternalError;
278         //    return muxer;
279         //});
280 
281 
282         #region  當作消息代理中間件使用 一般使用更專業的消息隊列來處理這種業務場景
283         /// <summary>
284         /// 當作消息代理中間件使用
285         /// 消息組建中,重要的概念便是生產者,消費者,消息中間件。
286         /// </summary>
287         /// <param name="channel"></param>
288         /// <param name="message"></param>
289         /// <returns></returns>
290         public static long Publish(string channel, string message)
291         {
292             ISubscriber sub = Instance.GetSubscriber();
293             //return sub.Publish("messages", "hello");
294             return sub.Publish(channel, message);
295         }
296 
297         /// <summary>
298         /// 在消費者端得到該消息並輸出
299         /// </summary>
300         /// <param name="channelFrom"></param>
301         /// <returns></returns>
302         public static void Subscribe(string channelFrom)
303         {
304             ISubscriber sub = Instance.GetSubscriber();
305             sub.Subscribe(channelFrom, (channel, message) =>
306             {
307                 Console.WriteLine((string)message);
308             });
309         }
310         #endregion
311 
312         /// <summary>
313         /// GetServer方法會接收一個EndPoint類或者一個唯一標識一台服務器的鍵值對
314         /// 有時候需要為單個服務器指定特定的命令
315         /// 使用IServer可以使用所有的shell命令,比如:
316         /// DateTime lastSave = server.LastSave();
317         /// ClientInfo[] clients = server.ClientList();
318         /// 如果報錯在連接字符串后加 ,allowAdmin=true;
319         /// </summary>
320         /// <returns></returns>
321         public static IServer GetServer(string host, int port)
322         {
323             IServer server = Instance.GetServer(host, port);
324             return server;
325         }
326 
327         /// <summary>
328         /// 獲取全部終結點
329         /// </summary>
330         /// <returns></returns>
331         public static EndPoint[] GetEndPoints()
332         {
333             EndPoint[] endpoints = Instance.GetEndPoints();
334             return endpoints;
335         }
336 
337     }
338 
339     internal class BaseSystemInfo
340     {
341         internal static readonly string SystemCode="000A";
342     }
View Code

測試代碼

 1  static void Main(string[] args)
 2         {
 3             RedisTest();
 4         }
 5         public static void RedisTest()
 6         {
 7             Console.WriteLine("Redis寫入緩存:Name:張三豐");
 8             StackExchangeRedisHelper.Set("Name", "張三豐", new TimeSpan(0, 0, 0, 0, 1000));
 9             Console.WriteLine("Redis獲取緩存:Name:" + StackExchangeRedisHelper.Get("Name").ToString());
10             Thread.Sleep(1000);
11             Console.WriteLine("一秒后Redis獲取緩存:Name:" + StackExchangeRedisHelper.Get("Name")??"");
12             Console.ReadKey();
13         }

 

 也可以通過Execute來直接運行redis命令

 

Redis加入Windows服務

由於關閉控制台redis就自動關閉了,所以把redis加入windows服務更好一些

切換到redis目錄下運行命令:redis-server --service-install redis.windows-service.conf --loglevel verbose

移除服務:--service-uninstal

開啟服務:redis-server --service-start

關閉服務:redis-server --service-stop

在開啟Redis服務時遇到一些坑,

  redis.windows-service.conf中配置:

  1. logfile "Logs/redis_log.txt"需要有對應的目錄

  2.將bind 127.0.0.1注釋去掉

  3.依然有問題,后參考一篇文章 http://blog.csdn.net/fengzhihen2007/article/details/52211048

直到出現successfully started服務啟動成功


免責聲明!

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



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