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 #region 属性 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, string value, TimeSpan? expiry = default(TimeSpan?)) 166 { 167 key = AddSysCustomKey(key); 168 return await Do(db => db.StringSetAsync(key, value, 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, RedisValue>(AddSysCustomKey(p.Key), 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, T obj, TimeSpan? expiry = default(TimeSpan?)) 192 { 193 key = AddSysCustomKey(key); 194 string json = ConvertJson(obj); 195 return await Do(db => db.StringSetAsync(key, json, 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, dataKey, 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, string dataKey, double val = 1) 373 { 374 key = AddSysCustomKey(key); 375 return Do(db => db.HashDecrement(key, dataKey, 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, string dataKey, T t) 425 { 426 key = AddSysCustomKey(key); 427 return await Do(db => 428 { 429 string json = ConvertJson(t); 430 return db.HashSetAsync(key, dataKey, 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, string dataKey, double val = 1) 481 { 482 key = AddSysCustomKey(key); 483 return await Do(db => db.HashIncrementAsync(key, dataKey, 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, string dataKey, double val = 1) 494 { 495 key = AddSysCustomKey(key); 496 return await Do(db => db.HashDecrementAsync(key, dataKey, 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, T value, double score) 782 { 783 key = AddSysCustomKey(key); 784 return await Do(redis => redis.SortedSetAddAsync(key, ConvertJson<T>(value), 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 }
测试中用到的HashSet和Get方法,其他的使用到的可以测试下,
1 public bool HashSet<T>(string key, string dataKey, T t) 2 { 3 key = AddSysCustomKey(key); 4 return Do(db => 5 { 6 string json = ConvertJson(t); 7 return db.HashSet(key, dataKey, json); 8 }); 9 }
④ Main函数中的测试用例,也只是简单测试了下,
1 string key = "123456"; 2 string dataKey = "123456"; 3 4 redisHelper.HashSet(key, dataKey, "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, dataKey, 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}, Age = {1}.", getStu.Name, getStu.Age); 13 getStu = redisHelper.ListLeftPop<Student>("PushTest"); 14 }
运行输出,前两个是刚才执行入队一个,现在执行一次程序又入队一个,所以,取出五个,与放入顺序一致,先进先出。