C#-Redis幫助類(.Net Framework)
1. Redis簡要介紹
引用百度百科的話,就是:Redis(Remote Dictionary Server ),即遠端字典服務,是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value NoSQL資料庫,並提供多種語言的API。
Redis的主要使用場景:快取、訊息佇列、頻繁讀寫等,還有很多等等,這個可以隨處搜到;Redis的優勢就是讀寫資料效能高,支援資料型別豐富,所有操作都是原子性,成功或者不成功,現在還支援釋出訂閱等特性。
2. .Net Framework操作Redis
建立新專案等等其他的我就不截圖了,我使用的是VS2019專業版,.Net Framework 4.7.2,都行,這個都支援,無非可能是類庫更新導致有些最新功能你不能用。
看下專案的一個結構,當前選中的為啟動專案,控制檯應用程式,另外兩個是用到的自定義類庫,RedisHelp為自定義的Redis幫助類庫,用到的Nuget包為StackExchange.Redis2.1.30,LogManager是一個寫日誌的幫助類;
①配置檔案配置,RedisTest專案展開,開啟App.config,新增Redis服務的IP和埠,<add name="RedisExchangeHosts" connectionString="127.0.0.1:6379,allowadmin=true" />
②ConnectionMultiplexer封裝
ConnectionMultiplexer物件是StackExchange.Redis最中樞的物件。這個類的例項需要被整個應用程式域共享和重用的,所以不需要在每個操作中不停的建立該物件的例項,一般都是使用單例來建立和存放這個物件,提高程式執行的效率,這個在官網上也有說明的。
1 /// <summary> 2 /// ConnectionMultiplexer物件管理幫助類 3 /// </summary> 4 public static class RedisConnectionHelp 5 { 6 #regionView Code屬性 7 8 /// <summary> 9 /// 系統自定義Key字首 10 /// </summary> 11 public static readonly string SysCustomKey = ConfigurationManager.AppSettings["redisKey"] ?? ""; 12 13 /// <summary> 14 /// Redis連結字串 15 /// </summary> 16 private static readonly string RedisConnectionString = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString; 17 18 /// <summary> 19 /// 連結快取池 20 /// </summary> 21 private static readonly ConcurrentDictionary<string,ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary<string,ConnectionMultiplexer>(); 22 23 #endregion 24 25 #region 單例和構造 26 27 /// <summary> 28 /// 鎖 29 /// </summary> 30 private static readonly object Locker = new object(); 31 32 /// <summary> 33 /// 單例 34 /// </summary> 35 private static ConnectionMultiplexer _instance; 36 37 38 /// <summary> 39 /// 單例獲取 40 /// </summary> 41 public static ConnectionMultiplexer Instance 42 { 43 get 44 { 45 if (_instance == null) 46 { 47 lock (Locker) 48 { 49 if (_instance == null || !_instance.IsConnected) 50 { 51 _instance = GetManager(); 52 } 53 } 54 } 55 return _instance; 56 } 57 } 58 59 /// <summary> 60 /// 快取獲取 61 /// </summary> 62 /// <param name="connectionString"></param> 63 /// <returns></returns> 64 public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString) 65 { 66 if (!ConnectionCache.ContainsKey(connectionString)) 67 { 68 ConnectionCache[connectionString] = GetManager(connectionString); 69 } 70 return ConnectionCache[connectionString]; 71 } 72 73 /// <summary> 74 /// 獲取連結 75 /// </summary> 76 /// <param name="connectionString"></param> 77 /// <returns></returns> 78 private static ConnectionMultiplexer GetManager(string connectionString = null) 79 { 80 connectionString = connectionString ?? RedisConnectionString; 81 var connect = ConnectionMultiplexer.Connect(connectionString); 82 83 //註冊如下事件 84 connect.ConnectionFailed += MuxerConnectionFailed; 85 connect.ConnectionRestored += MuxerConnectionRestored; 86 connect.ErrorMessage += MuxerErrorMessage; 87 connect.ConfigurationChanged += MuxerConfigurationChanged; 88 connect.HashSlotMoved += MuxerHashSlotMoved; 89 connect.InternalError += MuxerInternalError; 90 91 return connect; 92 } 93 94 #endregion 95 96 #region 事件 97 98 /// <summary> 99 /// 配置更改時 100 /// </summary> 101 /// <param name="sender"></param> 102 /// <param name="e"></param> 103 private static void MuxerConfigurationChanged(object sender,EndPointEventArgs e) 104 { 105 Console.WriteLine("Configuration changed: " + e.EndPoint); 106 } 107 108 /// <summary> 109 /// 發生錯誤時 110 /// </summary> 111 /// <param name="sender"></param> 112 /// <param name="e"></param> 113 private static void MuxerErrorMessage(object sender,RedisErrorEventArgs e) 114 { 115 Console.WriteLine("ErrorMessage: " + e.Message); 116 } 117 118 /// <summary> 119 /// 重新建立連線之前的錯誤 120 /// </summary> 121 /// <param name="sender"></param> 122 /// <param name="e"></param> 123 private static void MuxerConnectionRestored(object sender,ConnectionFailedEventArgs e) 124 { 125 Console.WriteLine("ConnectionRestored: " + e.EndPoint); 126 } 127 128 /// <summary> 129 /// 連線失敗 , 如果重新連線成功你將不會收到這個通知 130 /// </summary> 131 /// <param name="sender"></param> 132 /// <param name="e"></param> 133 private static void MuxerConnectionFailed(object sender,ConnectionFailedEventArgs e) 134 { 135 Console.WriteLine("重新連線:Endpoint failed: " + e.EndPoint + "," + e.FailureType + (e.Exception == null ? "" : ("," + e.Exception.Message))); 136 } 137 138 /// <summary> 139 /// 更改叢集 140 /// </summary> 141 /// <param name="sender"></param> 142 /// <param name="e"></param> 143 private static void MuxerHashSlotMoved(object sender,HashSlotMovedEventArgs e) 144 { 145 Console.WriteLine("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ",OldEndPoint" + e.OldEndPoint); 146 } 147 148 /// <summary> 149 /// redis類庫錯誤 150 /// </summary> 151 /// <param name="sender"></param> 152 /// <param name="e"></param> 153 private static void MuxerInternalError(object sender,InternalErrorEventArgs e) 154 { 155 Console.WriteLine("InternalError:Message" + e.Exception.Message); 156 } 157 158 #endregion 事件 159 }
③RedisHelper通用操作類封裝
1 /// <summary> 2 /// Redis操作類 3 /// </summary> 4 public class RedisHelper 5 { 6 #region 屬性 7 8 /// <summary> 9 /// DB庫 10 /// </summary> 11 private int DbNum { get; } 12 13 /// <summary> 14 /// Redis連結 15 /// </summary> 16 private readonly ConnectionMultiplexer _conn; 17 18 /// <summary> 19 /// 字首 20 /// </summary> 21 public string CustomKey; 22 23 #endregion 24 25 #region 建構函式 26 27 /// <summary> 28 /// 預設構造 29 /// </summary> 30 /// <param name="dbNum">DB索引</param> 31 public RedisHelper(int dbNum = 0) 32 : this(dbNum,null) 33 { 34 } 35 36 /// <summary> 37 /// 構造 38 /// </summary> 39 /// <param name="dbNum"></param> 40 /// <param name="readWriteHosts"></param> 41 public RedisHelper(int dbNum,string readWriteHosts) 42 { 43 DbNum = dbNum; 44 _conn = 45 string.IsNullOrWhiteSpace(readWriteHosts) ? 46 RedisConnectionHelp.Instance : 47 RedisConnectionHelp.GetConnectionMultiplexer(readWriteHosts); 48 } 49 50 #endregion 建構函式 51 52 #region String 53 54 #region 同步方法 55 56 /// <summary> 57 /// 儲存單個key value 58 /// </summary> 59 /// <param name="key">Redis Key</param> 60 /// <param name="value">儲存的值</param> 61 /// <param name="expiry">過期時間</param> 62 /// <returns></returns> 63 public bool StringSet(string key,string value,TimeSpan? expiry = default(TimeSpan?)) 64 { 65 key = AddSysCustomKey(key); 66 return Do(db => db.StringSet(key,value,expiry)); 67 } 68 69 /// <summary> 70 /// 儲存多個key value 71 /// </summary> 72 /// <param name="keyValues">鍵值對</param> 73 /// <returns></returns> 74 public bool StringSet(List<KeyValuePair<RedisKey,RedisValue>> keyValues) 75 { 76 List<KeyValuePair<RedisKey,RedisValue>> newkeyValues = 77 keyValues.Select(p => new KeyValuePair<RedisKey,RedisValue>(AddSysCustomKey(p.Key),p.Value)).ToList(); 78 return Do(db => db.StringSet(newkeyValues.ToArray())); 79 } 80 81 /// <summary> 82 /// 儲存一個物件 83 /// </summary> 84 /// <typeparam name="T"></typeparam> 85 /// <param name="key"></param> 86 /// <param name="obj"></param> 87 /// <param name="expiry"></param> 88 /// <returns></returns> 89 public bool StringSet<T>(string key,T obj,TimeSpan? expiry = default(TimeSpan?)) 90 { 91 key = AddSysCustomKey(key); 92 string json = ConvertJson(obj); 93 return Do(db => db.StringSet(key,json,expiry)); 94 } 95 96 /// <summary> 97 /// 獲取單個key的值 98 /// </summary> 99 /// <param name="key">Redis Key</param> 100 /// <returns></returns> 101 public string StringGet(string key) 102 { 103 key = AddSysCustomKey(key); 104 return Do(db => db.StringGet(key)); 105 } 106 107 /// <summary> 108 /// 獲取多個Key 109 /// </summary> 110 /// <param name="listKey">Redis Key集合</param> 111 /// <returns></returns> 112 public RedisValue[] StringGet(List<string> listKey) 113 { 114 List<string> newKeys = listKey.Select(AddSysCustomKey).ToList(); 115 return Do(db => db.StringGet(ConvertRedisKeys(newKeys))); 116 } 117 118 /// <summary> 119 /// 獲取一個key的物件 120 /// </summary> 121 /// <typeparam name="T"></typeparam> 122 /// <param name="key"></param> 123 /// <returns></returns> 124 public T StringGet<T>(string key) 125 { 126 key = AddSysCustomKey(key); 127 return Do(db => ConvertObj<T>(db.StringGet(key))); 128 } 129 130 /// <summary> 131 /// 為數字增長val 132 /// </summary> 133 /// <param name="key"></param> 134 /// <param name="val">可以為負</param> 135 /// <returns>增長後的值</returns> 136 public double StringIncrement(string key,double val = 1) 137 { 138 key = AddSysCustomKey(key); 139 return Do(db => db.StringIncrement(key,val)); 140 } 141 142 /// <summary> 143 /// 為數字減少val 144 /// </summary> 145 /// <param name="key"></param> 146 /// <param name="val">可以為負</param> 147 /// <returns>減少後的值</returns> 148 public double StringDecrement(string key,double val = 1) 149 { 150 key = AddSysCustomKey(key); 151 return Do(db => db.StringDecrement(key,val)); 152 } 153 154 #endregion 同步方法 155 156 #region 非同步方法 157 158 /// <summary> 159 /// 儲存單個key value 160 /// </summary> 161 /// <param name="key">Redis Key</param> 162 /// <param name="value">儲存的值</param> 163 /// <param name="expiry">過期時間</param> 164 /// <returns></returns> 165 public async Task<bool> StringSetAsync(string key,TimeSpan? expiry = default(TimeSpan?)) 166 { 167 key = AddSysCustomKey(key); 168 return await Do(db => db.StringSetAsync(key,expiry)); 169 } 170 171 /// <summary> 172 /// 儲存多個key value 173 /// </summary> 174 /// <param name="keyValues">鍵值對</param> 175 /// <returns></returns> 176 public async Task<bool> StringSetAsync(List<KeyValuePair<RedisKey,RedisValue>> keyValues) 177 { 178 List<KeyValuePair<RedisKey,RedisValue>> newkeyValues = 179 keyValues.Select(p => new KeyValuePair<RedisKey,p.Value)).ToList(); 180 return await Do(db => db.StringSetAsync(newkeyValues.ToArray())); 181 } 182 183 /// <summary> 184 /// 儲存一個物件 185 /// </summary> 186 /// <typeparam name="T"></typeparam> 187 /// <param name="key"></param> 188 /// <param name="obj"></param> 189 /// <param name="expiry"></param> 190 /// <returns></returns> 191 public async Task<bool> StringSetAsync<T>(string key,TimeSpan? expiry = default(TimeSpan?)) 192 { 193 key = AddSysCustomKey(key); 194 string json = ConvertJson(obj); 195 return await Do(db => db.StringSetAsync(key,expiry)); 196 } 197 198 /// <summary> 199 /// 獲取單個key的值 200 /// </summary> 201 /// <param name="key">Redis Key</param> 202 /// <returns></returns> 203 public async Task<string> StringGetAsync(string key) 204 { 205 key = AddSysCustomKey(key); 206 return await Do(db => db.StringGetAsync(key)); 207 } 208 209 /// <summary> 210 /// 獲取多個Key 211 /// </summary> 212 /// <param name="listKey">Redis Key集合</param> 213 /// <returns></returns> 214 public async Task<RedisValue[]> StringGetAsync(List<string> listKey) 215 { 216 List<string> newKeys = listKey.Select(AddSysCustomKey).ToList(); 217 return await Do(db => db.StringGetAsync(ConvertRedisKeys(newKeys))); 218 } 219 220 /// <summary> 221 /// 獲取一個key的物件 222 /// </summary> 223 /// <typeparam name="T"></typeparam> 224 /// <param name="key"></param> 225 /// <returns></returns> 226 public async Task<T> StringGetAsync<T>(string key) 227 { 228 key = AddSysCustomKey(key); 229 string result = await Do(db => db.StringGetAsync(key)); 230 return ConvertObj<T>(result); 231 } 232 233 /// <summary> 234 /// 為數字增長val 235 /// </summary> 236 /// <param name="key"></param> 237 /// <param name="val">可以為負</param> 238 /// <returns>增長後的值</returns> 239 public async Task<double> StringIncrementAsync(string key,double val = 1) 240 { 241 key = AddSysCustomKey(key); 242 return await Do(db => db.StringIncrementAsync(key,val)); 243 } 244 245 /// <summary> 246 /// 為數字減少val 247 /// </summary> 248 /// <param name="key"></param> 249 /// <param name="val">可以為負</param> 250 /// <returns>減少後的值</returns> 251 public async Task<double> StringDecrementAsync(string key,double val = 1) 252 { 253 key = AddSysCustomKey(key); 254 return await Do(db => db.StringDecrementAsync(key,val)); 255 } 256 257 #endregion 非同步方法 258 259 #endregion String 260 261 #region Hash 262 263 #region 同步方法 264 265 /// <summary> 266 /// 判斷某個資料是否已經被快取 267 /// </summary> 268 /// <param name="key"></param> 269 /// <param name="dataKey"></param> 270 /// <returns></returns> 271 public bool HashExists(string key,string dataKey) 272 { 273 key = AddSysCustomKey(key); 274 return Do(db => db.HashExists(key,dataKey)); 275 } 276 277 /// <summary> 278 /// 儲存資料到hash表 279 /// </summary> 280 /// <typeparam name="T"></typeparam> 281 /// <param name="key"></param> 282 /// <param name="dataKey"></param> 283 /// <param name="t"></param> 284 /// <returns></returns> 285 public bool HashSet<T>(string key,string dataKey,T t) 286 { 287 key = AddSysCustomKey(key); 288 return Do(db => 289 { 290 string json = ConvertJson(t); 291 return db.HashSet(key,dataKey,json); 292 }); 293 } 294 295 /// <summary> 296 /// 移除hash中的某值 297 /// </summary> 298 /// <param name="key"></param> 299 /// <param name="dataKey"></param> 300 /// <returns></returns> 301 public bool HashDelete(string key,string dataKey) 302 { 303 key = AddSysCustomKey(key); 304 return Do(db => db.HashDelete(key,dataKey)); 305 } 306 307 /// <summary> 308 /// 移除hash中的多個值 309 /// </summary> 310 /// <param name="key"></param> 311 /// <param name="dataKeys"></param> 312 /// <returns></returns> 313 public long HashDelete(string key,List<RedisValue> dataKeys) 314 { 315 key = AddSysCustomKey(key); 316 return Do(db => db.HashDelete(key,dataKeys.ToArray())); 317 } 318 319 /// <summary> 320 /// 從hash表獲取資料 321 /// </summary> 322 /// <typeparam name="T"></typeparam> 323 /// <param name="key"></param> 324 /// <param name="dataKey"></param> 325 /// <returns></returns> 326 public T HashGet<T>(string key,string dataKey) 327 { 328 key = AddSysCustomKey(key); 329 return Do(db => 330 { 331 string value = db.HashGet(key,dataKey); 332 return ConvertObj<T>(value); 333 }); 334 } 335 336 /// <summary> 337 /// 從hash表獲取資料 338 /// </summary> 339 /// <typeparam name="T"></typeparam> 340 /// <param name="key"></param> 341 /// <param name="dataKey"></param> 342 /// <returns></returns> 343 public string HashGetString(string key,string dataKey) 344 { 345 key = AddSysCustomKey(key); 346 return Do(db => 347 { 348 return db.HashGet(key,dataKey); 349 }); 350 } 351 352 /// <summary> 353 /// 為數字增長val 354 /// </summary> 355 /// <param name="key"></param> 356 /// <param name="dataKey"></param> 357 /// <param name="val">可以為負</param> 358 /// <returns>增長後的值</returns> 359 public double HashIncrement(string key,string dataKey,double val = 1) 360 { 361 key = AddSysCustomKey(key); 362 return Do(db => db.HashIncrement(key,val)); 363 } 364 365 /// <summary> 366 /// 為數字減少val 367 /// </summary> 368 /// <param name="key"></param> 369 /// <param name="dataKey"></param> 370 /// <param name="val">可以為負</param> 371 /// <returns>減少後的值</returns> 372 public double HashDecrement(string key,double val = 1) 373 { 374 key = AddSysCustomKey(key); 375 return Do(db => db.HashDecrement(key,val)); 376 } 377 378 /// <summary> 379 /// 獲取hashkey所有Redis key 380 /// </summary> 381 /// <typeparam name="T"></typeparam> 382 /// <param name="key"></param> 383 /// <returns></returns> 384 public List<T> HashKeys<T>(string key) 385 { 386 key = AddSysCustomKey(key); 387 return Do(db => 388 { 389 RedisValue[] values = db.HashKeys(key); 390 return ConvetList<T>(values); 391 }); 392 } 393 394 public List<string> HashKeysString<T>(string key) 395 { 396 key = AddSysCustomKey(key); 397 return Do<List<string>>(db => this.ConvertString<string>(db.HashKeys(key,CommandFlags.None))); 398 } 399 400 #endregion 同步方法 401 402 #region 非同步方法 403 404 /// <summary> 405 /// 判斷某個資料是否已經被快取 406 /// </summary> 407 /// <param name="key"></param> 408 /// <param name="dataKey"></param> 409 /// <returns></returns> 410 public async Task<bool> HashExistsAsync(string key,string dataKey) 411 { 412 key = AddSysCustomKey(key); 413 return await Do(db => db.HashExistsAsync(key,dataKey)); 414 } 415 416 /// <summary> 417 /// 儲存資料到hash表 418 /// </summary> 419 /// <typeparam name="T"></typeparam> 420 /// <param name="key"></param> 421 /// <param name="dataKey"></param> 422 /// <param name="t"></param> 423 /// <returns></returns> 424 public async Task<bool> HashSetAsync<T>(string key,T t) 425 { 426 key = AddSysCustomKey(key); 427 return await Do(db => 428 { 429 string json = ConvertJson(t); 430 return db.HashSetAsync(key,json); 431 }); 432 } 433 434 /// <summary> 435 /// 移除hash中的某值 436 /// </summary> 437 /// <param name="key"></param> 438 /// <param name="dataKey"></param> 439 /// <returns></returns> 440 public async Task<bool> HashDeleteAsync(string key,string dataKey) 441 { 442 key = AddSysCustomKey(key); 443 return await Do(db => db.HashDeleteAsync(key,dataKey)); 444 } 445 446 /// <summary> 447 /// 移除hash中的多個值 448 /// </summary> 449 /// <param name="key"></param> 450 /// <param name="dataKeys"></param> 451 /// <returns></returns> 452 public async Task<long> HashDeleteAsync(string key,List<RedisValue> dataKeys) 453 { 454 key = AddSysCustomKey(key); 455 //List<RedisValue> dataKeys1 = new List<RedisValue>() {"1","2"}; 456 return await Do(db => db.HashDeleteAsync(key,dataKeys.ToArray())); 457 } 458 459 /// <summary> 460 /// 從hash表獲取資料 461 /// </summary> 462 /// <typeparam name="T"></typeparam> 463 /// <param name="key"></param> 464 /// <param name="dataKey"></param> 465 /// <returns></returns> 466 public async Task<T> HashGeAsync<T>(string key,string dataKey) 467 { 468 key = AddSysCustomKey(key); 469 string value = await Do(db => db.HashGetAsync(key,dataKey)); 470 return ConvertObj<T>(value); 471 } 472 473 /// <summary> 474 /// 為數字增長val 475 /// </summary> 476 /// <param name="key"></param> 477 /// <param name="dataKey"></param> 478 /// <param name="val">可以為負</param> 479 /// <returns>增長後的值</returns> 480 public async Task<double> HashIncrementAsync(string key,double val = 1) 481 { 482 key = AddSysCustomKey(key); 483 return await Do(db => db.HashIncrementAsync(key,val)); 484 } 485 486 /// <summary> 487 /// 為數字減少val 488 /// </summary> 489 /// <param name="key"></param> 490 /// <param name="dataKey"></param> 491 /// <param name="val">可以為負</param> 492 /// <returns>減少後的值</returns> 493 public async Task<double> HashDecrementAsync(string key,double val = 1) 494 { 495 key = AddSysCustomKey(key); 496 return await Do(db => db.HashDecrementAsync(key,val)); 497 } 498 499 /// <summary> 500 /// 獲取hashkey所有Redis key 501 /// </summary> 502 /// <typeparam name="T"></typeparam> 503 /// <param name="key"></param> 504 /// <returns></returns> 505 public async Task<List<T>> HashKeysAsync<T>(string key) 506 { 507 key = AddSysCustomKey(key); 508 RedisValue[] values = await Do(db => db.HashKeysAsync(key)); 509 return ConvetList<T>(values); 510 } 511 512 #endregion 非同步方法 513 514 #endregion Hash 515 516 #region List 517 518 #region 同步方法 519 520 /// <summary> 521 /// 移除指定ListId的內部List的值 522 /// </summary> 523 /// <param name="key"></param> 524 /// <param name="value"></param> 525 public void ListRemove<T>(string key,T value) 526 { 527 key = AddSysCustomKey(key); 528 Do(db => db.ListRemove(key,ConvertJson(value))); 529 } 530 531 /// <summary> 532 /// 獲取指定key的List 533 /// </summary> 534 /// <param name="key"></param> 535 /// <returns></returns> 536 public List<T> ListRange<T>(string key) 537 { 538 key = AddSysCustomKey(key); 539 return Do(redis => 540 { 541 var values = redis.ListRange(key); 542 return ConvetList<T>(values); 543 }); 544 } 545 546 /// <summary> 547 /// 入隊 548 /// </summary> 549 /// <param name="key"></param> 550 /// <param name="value"></param> 551 public void ListRightPush<T>(string key,T value) 552 { 553 key = AddSysCustomKey(key); 554 Do(db => db.ListRightPush(key,ConvertJson(value))); 555 } 556 557 /// <summary> 558 /// 出隊 559 /// </summary> 560 /// <typeparam name="T"></typeparam> 561 /// <param name="key"></param> 562 /// <returns></returns> 563 public T ListRightPop<T>(string key) 564 { 565 key = AddSysCustomKey(key); 566 return Do(db => 567 { 568 var value = db.ListRightPop(key); 569 return ConvertObj<T>(value); 570 }); 571 } 572 573 /// <summary> 574 /// 入棧 575 /// </summary> 576 /// <typeparam name="T"></typeparam> 577 /// <param name="key"></param> 578 /// <param name="value"></param> 579 public void ListLeftPush<T>(string key,T value) 580 { 581 key = AddSysCustomKey(key); 582 Do(db => db.ListLeftPush(key,ConvertJson(value))); 583 } 584 585 /// <summary> 586 /// 出棧 587 /// </summary> 588 /// <typeparam name="T"></typeparam> 589 /// <param name="key"></param> 590 /// <returns></returns> 591 public T ListLeftPop<T>(string key) 592 { 593 key = AddSysCustomKey(key); 594 return Do(db => 595 { 596 var value = db.ListLeftPop(key); 597 return ConvertObj<T>(value); 598 }); 599 } 600 601 /// <summary> 602 /// 出棧 603 /// </summary> 604 /// <typeparam name="T"></typeparam> 605 /// <param name="key"></param> 606 /// <returns></returns> 607 public string ListLeftPopString(string key) 608 { 609 key = AddSysCustomKey(key); 610 return Do(db => 611 { 612 return db.ListLeftPop(key); 613 }); 614 } 615 616 /// <summary> 617 /// 獲取集合中的數量 618 /// </summary> 619 /// <param name="key"></param> 620 /// <returns></returns> 621 public long ListLength(string key) 622 { 623 key = AddSysCustomKey(key); 624 return Do(redis => redis.ListLength(key)); 625 } 626 627 #endregion 同步方法 628 629 #region 非同步方法 630 631 /// <summary> 632 /// 移除指定ListId的內部List的值 633 /// </summary> 634 /// <param name="key"></param> 635 /// <param name="value"></param> 636 public async Task<long> ListRemoveAsync<T>(string key,T value) 637 { 638 key = AddSysCustomKey(key); 639 return await Do(db => db.ListRemoveAsync(key,ConvertJson(value))); 640 } 641 642 /// <summary> 643 /// 獲取指定key的List 644 /// </summary> 645 /// <param name="key"></param> 646 /// <returns></returns> 647 public async Task<List<T>> ListRangeAsync<T>(string key) 648 { 649 key = AddSysCustomKey(key); 650 var values = await Do(redis => redis.ListRangeAsync(key)); 651 return ConvetList<T>(values); 652 } 653 654 /// <summary> 655 /// 入隊 656 /// </summary> 657 /// <param name="key"></param> 658 /// <param name="value"></param> 659 public async Task<long> ListRightPushAsync<T>(string key,T value) 660 { 661 key = AddSysCustomKey(key); 662 return await Do(db => db.ListRightPushAsync(key,ConvertJson(value))); 663 } 664 665 /// <summary> 666 /// 出隊 667 /// </summary> 668 /// <typeparam name="T"></typeparam> 669 /// <param name="key"></param> 670 /// <returns></returns> 671 public async Task<T> ListRightPopAsync<T>(string key) 672 { 673 key = AddSysCustomKey(key); 674 var value = await Do(db => db.ListRightPopAsync(key)); 675 return ConvertObj<T>(value); 676 } 677 678 /// <summary> 679 /// 入棧 680 /// </summary> 681 /// <typeparam name="T"></typeparam> 682 /// <param name="key"></param> 683 /// <param name="value"></param> 684 public async Task<long> ListLeftPushAsync<T>(string key,T value) 685 { 686 key = AddSysCustomKey(key); 687 return await Do(db => db.ListLeftPushAsync(key,ConvertJson(value))); 688 } 689 690 /// <summary> 691 /// 出棧 692 /// </summary> 693 /// <typeparam name="T"></typeparam> 694 /// <param name="key"></param> 695 /// <returns></returns> 696 public async Task<T> ListLeftPopAsync<T>(string key) 697 { 698 key = AddSysCustomKey(key); 699 var value = await Do(db => db.ListLeftPopAsync(key)); 700 return ConvertObj<T>(value); 701 } 702 703 /// <summary> 704 /// 獲取集合中的數量 705 /// </summary> 706 /// <param name="key"></param> 707 /// <returns></returns> 708 public async Task<long> ListLengthAsync(string key) 709 { 710 key = AddSysCustomKey(key); 711 return await Do(redis => redis.ListLengthAsync(key)); 712 } 713 714 #endregion 非同步方法 715 716 #endregion List 717 718 #region SortedSet 有序集合 719 720 #region 同步方法 721 722 /// <summary> 723 /// 新增 724 /// </summary> 725 /// <param name="key"></param> 726 /// <param name="value"></param> 727 /// <param name="score"></param> 728 public bool SortedSetAdd<T>(string key,T value,double score) 729 { 730 key = AddSysCustomKey(key); 731 return Do(redis => redis.SortedSetAdd(key,ConvertJson<T>(value),score)); 732 } 733 734 /// <summary> 735 /// 刪除 736 /// </summary> 737 /// <param name="key"></param> 738 /// <param name="value"></param> 739 public bool SortedSetRemove<T>(string key,T value) 740 { 741 key = AddSysCustomKey(key); 742 return Do(redis => redis.SortedSetRemove(key,ConvertJson(value))); 743 } 744 745 /// <summary> 746 /// 獲取全部 747 /// </summary> 748 /// <param name="key"></param> 749 /// <returns></returns> 750 public List<T> SortedSetRangeByRank<T>(string key) 751 { 752 key = AddSysCustomKey(key); 753 return Do(redis => 754 { 755 var values = redis.SortedSetRangeByRank(key); 756 return ConvetList<T>(values); 757 }); 758 } 759 760 /// <summary> 761 /// 獲取集合中的數量 762 /// </summary> 763 /// <param name="key"></param> 764 /// <returns></returns> 765 public long SortedSetLength(string key) 766 { 767 key = AddSysCustomKey(key); 768 return Do(redis => redis.SortedSetLength(key)); 769 } 770 771 #endregion 同步方法 772 773 #region 非同步方法 774 775 /// <summary> 776 /// 新增 777 /// </summary> 778 /// <param name="key"></param> 779 /// <param name="value"></param> 780 /// <param name="score"></param> 781 public async Task<bool> SortedSetAddAsync<T>(string key,double score) 782 { 783 key = AddSysCustomKey(key); 784 return await Do(redis => redis.SortedSetAddAsync(key,score)); 785 } 786 787 /// <summary> 788 /// 刪除 789 /// </summary> 790 /// <param name="key"></param> 791 /// <param name="value"></param> 792 public async Task<bool> SortedSetRemoveAsync<T>(string key,T value) 793 { 794 key = AddSysCustomKey(key); 795 return await Do(redis => redis.SortedSetRemoveAsync(key,ConvertJson(value))); 796 } 797 798 /// <summary> 799 /// 獲取全部 800 /// </summary> 801 /// <param name="key"></param> 802 /// <returns></returns> 803 public async Task<List<T>> SortedSetRangeByRankAsync<T>(string key) 804 { 805 key = AddSysCustomKey(key); 806 var values = await Do(redis => redis.SortedSetRangeByRankAsync(key)); 807 return ConvetList<T>(values); 808 } 809 810 /// <summary> 811 /// 獲取集合中的數量 812 /// </summary> 813 /// <param name="key"></param> 814 /// <returns></returns> 815 public async Task<long> SortedSetLengthAsync(string key) 816 { 817 key = AddSysCustomKey(key); 818 return await Do(redis => redis.SortedSetLengthAsync(key)); 819 } 820 821 #endregion 非同步方法 822 823 #endregion SortedSet 有序集合 824 825 #region key 826 827 /// <summary> 828 /// 刪除單個key 829 /// </summary> 830 /// <param name="key">redis key</param> 831 /// <returns>是否刪除成功</returns> 832 public bool KeyDelete(string key) 833 { 834 key = AddSysCustomKey(key); 835 return Do(db => db.KeyDelete(key)); 836 } 837 838 /// <summary> 839 /// 刪除多個key 840 /// </summary> 841 /// <param name="keys">rediskey</param> 842 /// <returns>成功刪除的個數</returns> 843 public long KeyDelete(List<string> keys) 844 { 845 List<string> newKeys = keys.Select(AddSysCustomKey).ToList(); 846 return Do(db => db.KeyDelete(ConvertRedisKeys(newKeys))); 847 } 848 849 /// <summary> 850 /// 判斷key是否儲存 851 /// </summary> 852 /// <param name="key">redis key</param> 853 /// <returns></returns> 854 public bool KeyExists(string key) 855 { 856 key = AddSysCustomKey(key); 857 return Do(db => db.KeyExists(key)); 858 } 859 860 /// <summary> 861 /// 重新命名key 862 /// </summary> 863 /// <param name="key">就的redis key</param> 864 /// <param name="newKey">新的redis key</param> 865 /// <returns></returns> 866 public bool KeyRename(string key,string newKey) 867 { 868 key = AddSysCustomKey(key); 869 return Do(db => db.KeyRename(key,newKey)); 870 } 871 872 /// <summary> 873 /// 設定Key的時間 874 /// </summary> 875 /// <param name="key">redis key</param> 876 /// <param name="expiry"></param> 877 /// <returns></returns> 878 public bool KeyExpire(string key,TimeSpan? expiry = default(TimeSpan?)) 879 { 880 key = AddSysCustomKey(key); 881 return Do(db => db.KeyExpire(key,expiry)); 882 } 883 884 #endregion key 885 886 #region 釋出訂閱 887 888 /// <summary> 889 /// Redis釋出訂閱 訂閱 890 /// </summary> 891 /// <param name="subChannel"></param> 892 /// <param name="handler"></param> 893 public void Subscribe(string subChannel,Action<RedisChannel,RedisValue> handler = null) 894 { 895 ISubscriber sub = _conn.GetSubscriber(); 896 sub.Subscribe(subChannel,(channel,message) => 897 { 898 if (handler == null) 899 { 900 Console.WriteLine(subChannel + " 訂閱收到訊息:" + message); 901 } 902 else 903 { 904 handler(channel,message); 905 } 906 }); 907 } 908 909 /// <summary> 910 /// Redis釋出訂閱 釋出 911 /// </summary> 912 /// <typeparam name="T"></typeparam> 913 /// <param name="channel"></param> 914 /// <param name="msg"></param> 915 /// <returns></returns> 916 public long Publish<T>(string channel,T msg) 917 { 918 ISubscriber sub = _conn.GetSubscriber(); 919 return sub.Publish(channel,ConvertJson(msg)); 920 } 921 922 /// <summary> 923 /// Redis釋出訂閱 取消訂閱 924 /// </summary> 925 /// <param name="channel"></param> 926 public void Unsubscribe(string channel) 927 { 928 ISubscriber sub = _conn.GetSubscriber(); 929 sub.Unsubscribe(channel); 930 } 931 932 /// <summary> 933 /// Redis釋出訂閱 取消全部訂閱 934 /// </summary> 935 public void UnsubscribeAll() 936 { 937 ISubscriber sub = _conn.GetSubscriber(); 938 sub.UnsubscribeAll(); 939 } 940 941 #endregion 釋出訂閱 942 943 #region 其他 944 945 public ITransaction CreateTransaction() 946 { 947 return GetDatabase().CreateTransaction(); 948 } 949 950 public IDatabase GetDatabase() 951 { 952 return _conn.GetDatabase(DbNum); 953 } 954 955 public IServer GetServer(string hostAndPort) 956 { 957 return _conn.GetServer(hostAndPort); 958 } 959 960 /// <summary> 961 /// 設定字首 962 /// </summary> 963 /// <param name="customKey"></param> 964 public void SetSysCustomKey(string customKey) 965 { 966 CustomKey = customKey; 967 } 968 969 /// <summary> 970 /// 刪除集合 971 /// </summary> 972 /// <param name="redisKey"></param> 973 /// <param name="databaseNum"></param> 974 /// <returns></returns> 975 public bool KeyRemove(string redisKey) 976 { 977 var database = _conn.GetDatabase(DbNum); 978 return database.KeyDelete(redisKey); 979 } 980 981 #endregion 其他 982 983 #region 輔助方法 984 985 private string AddSysCustomKey(string oldKey) 986 { 987 var prefixKey = CustomKey ?? RedisConnectionHelp.SysCustomKey; 988 return prefixKey + oldKey; 989 } 990 991 private T Do<T>(Func<IDatabase,T> func) 992 { 993 var database = _conn.GetDatabase(DbNum); 994 return func(database); 995 } 996 997 private string ConvertJson<T>(T value) 998 { 999 string result = value is string ? value.ToString() : JsonConvert.SerializeObject(value); 1000 return result; 1001 } 1002 1003 private T ConvertObj<T>(RedisValue value) 1004 { 1005 if (value.IsNull) 1006 return default(T); 1007 return JsonConvert.DeserializeObject<T>(value); 1008 } 1009 1010 private List<T> ConvetList<T>(RedisValue[] values) 1011 { 1012 if (values == null) 1013 return null; 1014 1015 List<T> result = new List<T>(); 1016 foreach (var item in values) 1017 { 1018 var model = ConvertObj<T>(item); 1019 result.Add(model); 1020 } 1021 return result; 1022 } 1023 1024 private List<string> ConvertString<T>(RedisValue[] values) 1025 { 1026 List<string> list = new List<string>(); 1027 if (values == null) 1028 { 1029 return null; 1030 } 1031 foreach (RedisValue value2 in values) 1032 { 1033 list.Add(value2.ToString()); 1034 } 1035 return list; 1036 } 1037 1038 private RedisKey[] ConvertRedisKeys(List<string> redisKeys) 1039 { 1040 return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray(); 1041 } 1042 1043 #endregion 輔助方法 1044 }View Code
測試中用到的HashSet和Get方法,其他的使用到的可以測試下,
1 public bool HashSet<T>(string key,T t) 2 { 3 key = AddSysCustomKey(key); 4 return Do(db => 5 { 6 string json = ConvertJson(t); 7 return db.HashSet(key,json); 8 }); 9 }
④Main函式中的測試用例,也只是簡單測試了下,
1 string key = "123456"; 2 string dataKey = "123456"; 3 4 redisHelper.HashSet(key,"123456"); 5 6 string x = redisHelper.HashGetString(key,dataKey); 7 Console.WriteLine("x = {0}",x); 8 9 10 Student student = new Student { Age = 11,Name = "Jack" }; 11 redisHelper = new RedisHelper(1); 12 redisHelper.HashSet(key,student); 13 14 Student getStu = redisHelper.HashGet<Student>(key,dataKey); 15 if(getStu != null) 16 { 17 Console.WriteLine("Name = {0},Age = {1}.",getStu.Name,getStu.Age); 18 } 19 else 20 { 21 Console.WriteLine("Get student failure."); 22 }
輸出結果:
檢視Redis快取中儲存的資料,使用Redis客戶端進行檢視,因為程式碼中間redisHelper進行了重新構造,所以下圖會在兩個DB中。
Redis中值(value)可以是 字串(String),雜湊(Hash),列表(list),集合(sets) 和 有序集合(sorted sets)等型別。
測試下,佇列在Redis中的應用,入隊(左進右出,右進左出都有,組合就是棧和佇列啦),redisHelper.ListRightPush("PushTest",student);
再用Redis客戶端檢視,與用Hash儲存的不一樣,Redis佇列也可以放心使用,日活百萬以下沒什麼問題,再往上考慮Kafka呀,
使用ListLeftPop,右進左出的佇列,程式碼:
1 Console.WriteLine("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0"); 2 3 for(int i = 0; i < 3; i++) 4 { 5 student = new Student { Age = 11 + i,Name = string.Format("Jack {0}",i) }; 6 redisHelper.ListRightPush("PushTest",student); 7 } 8 9 getStu = redisHelper.ListLeftPop<Student>("PushTest"); 10 while (getStu != null) 11 { 12 Console.WriteLine("Name = {0},getStu.Age); 13 getStu = redisHelper.ListLeftPop<Student>("PushTest"); 14 }
執行輸出,前兩個是剛才執行入隊一個,現在執行一次程式又入隊一個,所以,取出五個,與放入順序一致,先進先出。