StackExchange.Redis通用封裝類分享

来源:http://www.cnblogs.com/qtqq/archive/2016/10/11/5951201.html
-Advertisement-
Play Games

前兩天朋友問我,有沒有使用過StackExchange.Redis,問我要個封裝類,由於之前都是使用ServiceStack.Redis,由於ServiceStack.Redis v4版本後是收費版的,所以現在也很有公司都在使用StackExchange.Redis而拋棄ServiceStack.R ...


  前兩天朋友問我,有沒有使用過StackExchange.Redis,問我要個封裝類,由於之前都是使用ServiceStack.Redis,由於ServiceStack.Redis v4版本後是收費版的,所以現在也很有公司都在使用StackExchange.Redis而拋棄ServiceStack.Redis了。其實個人覺得,兩個驅動都不錯,只是由於ServiceStack.Redis收費導致目前很多公司都是基於V3版本的使用,也有人說V3版本有很多Bug,沒有維護和升級,不過至少目前我是沒發現Bug。

  不過ServiceStack.Redis同StackExchange.Redis比較,拋開收費的來說,確認比StackExchange.Redis 更有優勢。StackExchange.Redis文檔很少,更不要說國內的文檔了,連github上面對應的介紹文檔都是很片面,這點我真的覺得StackExchange.Redis的作者至少要完善下文檔,很多都是要看源碼的例子才有。網上對StackExchange.Redis的使用例子也比ServiceStack.Redis少得多,不是說沒人用,只是我查來查去,大部分都是基於String類型的數據進行使用的封裝類,對於List,SortedSet,Hash的封裝操作都很少,基本都是東寫一點,西寫一點,很難找到完整的。在參考了一些文章和源碼後,這裡提供一個自己封裝的類,基本提供對於各種類型的使用封裝,提供給大家學習使用,如果有哪裡寫的不好的,大家也可以互相交流。

 

  ConnectionMultiplexer 封裝

  首先是 ConnectionMultiplexer 的封裝,ConnectionMultiplexer對象是StackExchange.Redis最中樞的對象。這個類的實例需要被整個應用程式域共用和重用的,所以不需要在每個操作中不停的創建該對象的實例,一般都是使用單例來創建和存放這個對象,這個在官網上也有說明。




  1  /// <summary>
  2     /// ConnectionMultiplexer對象管理幫助類
  3     /// </summary>
  4     public static class RedisConnectionHelp
  5     {
  6         //系統自定義Key首碼
  7         public static readonly string SysCustomKey = ConfigurationManager.AppSettings["redisKey"] ?? "";
  8 
  9         //"127.0.0.1:6379,allowadmin=true
 10         private static readonly string RedisConnectionString = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString;
 11 
 12         private static readonly object Locker = new object();
 13         private static ConnectionMultiplexer _instance;
 14         private static readonly ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary<string, ConnectionMultiplexer>();
 15 
 16         /// <summary>
 17         /// 單例獲取
 18         /// </summary>
 19         public static ConnectionMultiplexer Instance
 20         {
 21             get
 22             {
 23                 if (_instance == null)
 24                 {
 25                     lock (Locker)
 26                     {
 27                         if (_instance == null || !_instance.IsConnected)
 28                         {
 29                             _instance = GetManager();
 30                         }
 31                     }
 32                 }
 33                 return _instance;
 34             }
 35         }
 36 
 37         /// <summary>
 38         /// 緩存獲取
 39         /// </summary>
 40         /// <param name="connectionString"></param>
 41         /// <returns></returns>
 42         public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString)
 43         {
 44             if (!ConnectionCache.ContainsKey(connectionString))
 45             {
 46                 ConnectionCache[connectionString] = GetManager(connectionString);
 47             }
 48             return ConnectionCache[connectionString];
 49         }
 50 
 51         private static ConnectionMultiplexer GetManager(string connectionString = null)
 52         {
 53             connectionString = connectionString ?? RedisConnectionString;
 54             var connect = ConnectionMultiplexer.Connect(connectionString);
 55 
 56             //註冊如下事件
 57             connect.ConnectionFailed += MuxerConnectionFailed;
 58             connect.ConnectionRestored += MuxerConnectionRestored;
 59             connect.ErrorMessage += MuxerErrorMessage;
 60             connect.ConfigurationChanged += MuxerConfigurationChanged;
 61             connect.HashSlotMoved += MuxerHashSlotMoved;
 62             connect.InternalError += MuxerInternalError;
 63 
 64             return connect;
 65         }
 66 
 67         #region 事件
 68 
 69         /// <summary>
 70         /// 配置更改時
 71         /// </summary>
 72         /// <param name="sender"></param>
 73         /// <param name="e"></param>
 74         private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
 75         {
 76             Console.WriteLine("Configuration changed: " + e.EndPoint);
 77         }
 78 
 79         /// <summary>
 80         /// 發生錯誤時
 81         /// </summary>
 82         /// <param name="sender"></param>
 83         /// <param name="e"></param>
 84         private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
 85         {
 86             Console.WriteLine("ErrorMessage: " + e.Message);
 87         }
 88 
 89         /// <summary>
 90         /// 重新建立連接之前的錯誤
 91         /// </summary>
 92         /// <param name="sender"></param>
 93         /// <param name="e"></param>
 94         private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
 95         {
 96             Console.WriteLine("ConnectionRestored: " + e.EndPoint);
 97         }
 98 
 99         /// <summary>
100         /// 連接失敗 , 如果重新連接成功你將不會收到這個通知
101         /// </summary>
102         /// <param name="sender"></param>
103         /// <param name="e"></param>
104         private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
105         {
106             Console.WriteLine("重新連接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
107         }
108 
109         /// <summary>
110         /// 更改集群
111         /// </summary>
112         /// <param name="sender"></param>
113         /// <param name="e"></param>
114         private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
115         {
116             Console.WriteLine("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
117         }
118 
119         /// <summary>
120         /// redis類庫錯誤
121         /// </summary>
122         /// <param name="sender"></param>
123         /// <param name="e"></param>
124         private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
125         {
126             Console.WriteLine("InternalError:Message" + e.Exception.Message);
127         }
128 
129         #endregion 事件
130     }
ConnectionMultiplexer幫助類

  RedisHelper 通用操作類封  

 1  public class RedisHelper
 2     {
 3         private int DbNum { get; }
 4         private readonly ConnectionMultiplexer _conn;
 5         public string CustomKey;
 6 
 7         #region 構造函數
 8 
 9         public RedisHelper(int dbNum = 0)
10                 : this(dbNum, null)
11         {
12         }
13 
14         public RedisHelper(int dbNum, string readWriteHosts)
15         {
16             DbNum = dbNum;
17             _conn =
18                 string.IsNullOrWhiteSpace(readWriteHosts) ?
19                 RedisConnectionHelp.Instance :
20                 RedisConnectionHelp.GetConnectionMultiplexer(readWriteHosts);
21         }
22 
23 #region 輔助方法
24 
25         private string AddSysCustomKey(string oldKey)
26         {
27             var prefixKey = CustomKey ?? RedisConnectionHelp.SysCustomKey;
28             return prefixKey + oldKey;
29         }
30 
31         private T Do<T>(Func<IDatabase, T> func)
32         {
33             var database = _conn.GetDatabase(DbNum);
34             return func(database);
35         }
36 
37         private string ConvertJson<T>(T value)
38         {
39             string result = value is string ? value.ToString() : JsonConvert.SerializeObject(value);
40             return result;
41         }
42 
43         private T ConvertObj<T>(RedisValue value)
44         {
45             return JsonConvert.DeserializeObject<T>(value);
46         }
47 
48         private List<T> ConvetList<T>(RedisValue[] values)
49         {
50             List<T> result = new List<T>();
51             foreach (var item in values)
52             {
53                 var model = ConvertObj<T>(item);
54                 result.Add(model);
55             }
56             return result;
57         }
58 
59         private RedisKey[] ConvertRedisKeys(List<string> redisKeys)
60         {
61             return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();
62         }
63 
64         #endregion 輔助方法
65 
66         #endregion 構造函數
67 }
RedisHelper
  其中CustomKey用來表示系統首碼,AddSysCustomKey方法對每個key都進行首碼的添加處理,這裡推薦大家在命名redis的key的時候最好的加上首碼,並且使用 :來分割首碼 ,這裡在使用可視化工具查看的時候就比較好區分,比如我的的首碼是 Demo:test:(一般是  系統名:業務名:,然後你查看的時候你會發現整齊,好區分了很多

 

  String類型的封裝

  1 #region String
  2 
  3         #region 同步方法
  4 
  5         /// <summary>
  6         /// 保存單個key value
  7         /// </summary>
  8         /// <param name="key">Redis Key</param>
  9         /// <param name="value">保存的值</param>
 10         /// <param name="expiry">過期時間</param>
 11         /// <returns></returns>
 12         public bool StringSet(string key, string value, TimeSpan? expiry = default(TimeSpan?))
 13         {
 14             key = AddSysCustomKey(key);
 15             return Do(db => db.StringSet(key, value, expiry));
 16         }
 17 
 18         /// <summary>
 19         /// 保存多個key value
 20         /// </summary>
 21         /// <param name="keyValues">鍵值對</param>
 22         /// <returns></returns>
 23         public bool StringSet(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
 24         {
 25             List<KeyValuePair<RedisKey, RedisValue>> newkeyValues =
 26                 keyValues.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
 27             return Do(db => db.StringSet(newkeyValues.ToArray()));
 28         }
 29 
 30         /// <summary>
 31         /// 保存一個對象
 32         /// </summary>
 33         /// <typeparam name="T"></typeparam>
 34         /// <param name="key"></param>
 35         /// <param name="obj"></param>
 36         /// <param name="expiry"></param>
 37         /// <returns></returns>
 38         public bool StringSet<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
 39         {
 40             key = AddSysCustomKey(key);
 41             string json = ConvertJson(obj);
 42             return Do(db => db.StringSet(key, json, expiry));
 43         }
 44 
 45         /// <summary>
 46         /// 獲取單個key的值
 47         /// </summary>
 48         /// <param name="key">Redis Key</param>
 49         /// <returns></returns>
 50         public string StringGet(string key)
 51         {
 52             key = AddSysCustomKey(key);
 53             return Do(db => db.StringGet(key));
 54         }
 55 
 56         /// <summary>
 57         /// 獲取多個Key
 58         /// </summary>
 59         /// <param name="listKey">Redis Key集合</param>
 60         /// <returns></returns>
 61         public RedisValue[] StringGet(List<string> listKey)
 62         {
 63             List<string> newKeys = listKey.Select(AddSysCustomKey).ToList();
 64             return Do(db => db.StringGet(ConvertRedisKeys(newKeys)));
 65         }
 66 
 67         /// <summary>
 68         /// 獲取一個key的對象
 69         /// </summary>
 70         /// <typeparam name="T"></typeparam>
 71         /// <param name="key"></param>
 72         /// <returns></returns>
 73         public T StringGet<T>(string key)
 74         {
 75             key = AddSysCustomKey(key);
 76             return Do(db => ConvertObj<T>(db.StringGet(key)));
 77         }
 78 
 79         /// <summary>
 80         /// 為數字增長val
 81         /// </summary>
 82         /// <param name="key"></param>
 83         /// <param name="val">可以為負</param>
 84         /// <returns>增長後的值</returns>
 85         public double StringIncrement(string key, double val = 1)
 86         {
 87             key = AddSysCustomKey(key);
 88             return Do(db => db.StringIncrement(key, val));
 89         }
 90 
 91         /// <summary>
 92         /// 為數字減少val
 93         /// </summary>
 94         /// <param name="key"></param>
 95         /// <param name="val">可以為負</param>
 96         /// <returns>減少後的值</returns>
 97         public double StringDecrement(string key, double val = 1)
 98         {
 99             key = AddSysCustomKey(key);
100             return Do(db => db.StringDecrement(key, val));
101         }
102 
103         #endregion 同步方法
104 
105         #region 非同步方法
106 
107         /// <summary>
108         /// 保存單個key value
109         /// </summary>
110         /// <param name="key">Redis Key</param>
111         /// <param name="value">保存的值</param>
112         /// <param name="expiry">過期時間</param>
113         /// <returns></returns>
114         public async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = default(TimeSpan?))
115         {
116             key = AddSysCustomKey(key);
117             return await Do(db => db.StringSetAsync(key, value, expiry));
118         }
119 
120         /// <summary>
121         /// 保存多個key value
122         /// </summary>
123         /// <param name="keyValues">鍵值對</param>
124         /// <returns></returns>
125         public async Task<bool> StringSetAsync(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
126         {
127             List<KeyValuePair<RedisKey, RedisValue>> newkeyValues =
128                 keyValues.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
129             return await Do(db => db.StringSetAsync(newkeyValues.ToArray()));
130         }
131 
132         /// <summary>
133         /// 保存一個對象
134         /// </summary>
135         /// <typeparam name="T"></typeparam>
136         /// <param name="key"></param>
137         /// <param name="obj"></param>
138         /// <param name="expiry"></param>
139         /// <returns></returns>
140         public async Task<bool> StringSetAsync<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
141         {
142             key = AddSysCustomKey(key);
143             string json = ConvertJson(obj);
144             return await Do(db => db.StringSetAsync(key, json, expiry));
145         }
146 
147         /// <summary>
148         /// 獲取單個key的值
149         /// </summary>
150         /// <param name="key">Redis Key</param>
151         /// <returns></returns>
152         public async Task<string> StringGetAsync(string key)
153         {
154             key = AddSysCustomKey(key);
155             return await Do(db => db.StringGetAsync(key));
156         }
157 
158         /// <summary>
159         /// 獲取多個Key
160         /// </summary>
161         /// <param name="listKey">Redis Key集合</param>
162         /// <returns></returns>
163         public async Task<RedisValue[]> StringGetAsync(List<string> listKey)
164         {
165             List<string> newKeys = listKey.Select(AddSysCustomKey).ToList();
166             return await Do(db => db.StringGetAsync(ConvertRedisKeys(newKeys)));
167         }
168 
169         /// <summary>
170         /// 獲取一個key的對象
171         /// </summary>
172         /// <typeparam name="T"></typeparam>
173         /// <param name="key"></param>
174         /// <returns></returns>
175         public async Task<T> StringGetAsync<T>(string key)
176         {
177             key = AddSysCustomKey(key);
178             string result = await Do(db => db.StringGetAsync(key));
179             return ConvertObj<T>(result);
180         }
181 
182         /// <summary>
183         /// 為數字增長val
184         /// </summary>
185         /// <param name="key"></param>
186         /// <param name="val">可以為負</param>
187         /// <returns>增長後的值</returns>
188         public async Task<double> StringIncrementAsync(string key, double val = 1)
189         {
190             key = AddSysCustomKey(key);
191             return await Do(db => db.StringIncrementAsync(key, val));
192         }
193 
194         /// <summary>
195         /// 為數字減少val
196         /// </summary>
197         /// <param name="key"></param>
198         /// <param name="val">可以為負</param>
199         /// <returns>減少後的值</returns>
200         public async Task<double> StringDecrementAsync(string key, double val = 1)
201         {
202             key = AddSysCustomKey(key);
203             return await Do(db => db.StringDecrementAsync(key, val));
204         }
205 
206         #endregion 非同步方法
207 
208         #endregion String
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 昨天公司讓寫個實時監控網頁文件的變化情況,我就把我寫的代碼給大家分享一下。 本人技術不是很嫻熟,哪裡寫的有問題請多多指點,小生先謝謝了。 這裡用到了對文件的讀、寫、拷貝,刪除等操作,計時器的使用操作。 using System; using System.Collections.Generic; u ...
  • Areas 是 ASP.NET MVC 用來將相關功能組織成一組單獨命名空間(路由)和文件夾結構(視圖)的功能。使用 Areas 創建層次結構的路由,是通過添加另一個路由參數 `area` 到 `Controller` 和 `action`。 Areas 提供了一種把大型 ASP.NET Core... ...
  • DataBinding is one of the most powerful features in WPF. But because it resolves the bindings at runtime and does not throw exceptions, it's sometimes ...
  • WPF拖動DataGrid滾動條時內容混亂的解決方法 在WPF中,如果DataGrid里使用了模板列,當拖動滾動條時,往往會出現列表內容顯示混亂的情況。解決方法就是在Binding的時候給UpdateSourceTrigger賦值。 後臺代碼如下: ...
  • 1、介紹 vs15是微軟打造的新一代IDE,全新的安裝方式。官網介紹如下(https://blogs.msdn.microsoft.com/visualstudio/2016/10/05/announcing-visual-studio-15-preview-5/): 據微軟描述,Preview 5... ...
  • CUP和.NET SQL版本不同也會存在少許差距,但不會有質變,下麵的測試結果僅供參考 比賽規則 1.統一使用Realse版本的最新 DLL,Realse模式啟用程式 2.為了平衡CPU和資料庫空閑情況,使用車輪戰,每場比賽連續10回合比試 3.多次重啟電腦取平均成績上圖 比賽成員 1.SqlSug ...
  • 目錄 1.簡介... 2 2.適用範圍... 2 3.規範目的... 2 4.代碼組織與風格... 2 4.1 Tab鍵... 2 4.2 縮進... 3 4.3空行... 3 4.4函數長度... 3 4.5行寬... 3 4.6{ “,”} 3 5.文件命名... 3 6.命名... 4 6.1 ...
  • 什麼是ORM? 對象關係映射(英語:Object Relation Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程式技術,用於實現面向對象編程語言里不同類型系統的數據之間的轉換。從效果上說,它其實是創建了一個可在編程語言里使用的“虛擬對象資料庫”。 一般的ORM包括以下 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...