Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍
目录
- 简介
- 安装
- 入门指令
- GUI 工具
- C# 驱动介绍
简介
ANSI C 编写,开源,基于内存,可持久化,一个键值对的数据库,用法简单。
支持的类型:字符串、散列、列表、集合和有序集合。
因为 Redis 默认将所有数据都存储到内存中,并且内存的读写速度远远高于硬盘,因此,比其他基于硬盘存储的数据库在性能上体现的优势非常明显。不过这样也引发了一个数据安全性的问题,程序异常或退出后数据会出现丢失的情形,现在新的版本已经提供了数据持久化(RDB + AOF)的支持,即可以将内存中的数据异步写入到硬盘上,同时不会影响其它功能的运行。
redis 可以为每个键设置生存时间,到期自动删除,也就是说可以作为缓存系统(这也是企业主要的运用场景)进行使用。
相对于 Memcached,简单的说:Redis 单线程模型,Memcached 支持多线程,但 Redis 支持的功能和数据类型更多,更简单易用,并且 redis 的性能在绝大部分场合下都不会成为系统瓶颈,不过在多核服务器上使用的情况下,理论上 Memcached 比 redis 性能更高。所以,在新项目中,建议使用 redis 代替 Memcached。
Redis 还可以限定数据占用的最大内存空间,在数据达到空间限制后按一定规则自动淘汰不需要的键;也支持构建高性能的队列(不过很多企业会选择第三方的 MQ,如:RabbitMQ)。
安装
它的约定次版本号(即第一个小数点后的数字)为偶数的版本是稳定版(如 v2.8,v3.0)。
为了减少学习成本,我们直接使用 windows 版本的就可以,想学习 Linux 部署的,先搜搜别人的文章吧。
redis-windows-3.0(搜索了一下,最新的正式版是 3.2):下载地址
文件简单说明:
入门指令
1.启动 CMD:
$ redis-server$ redis-server --port 6380 //自定义端口
2.停止:
$ redis-cli SHUTDOWN
3.PING 命令:
测试与 redis 的连接是否正常,正常返回 PONG
$ redis-cli PING
GUI 工具
Redis Client:一个基于Java SWT 和 Jedis 编写的 redis 客户端 GUI 工具。可从 https://github.com/caoxinyu/RedisClient 下载。
从图可知,redis 包含了 16 个数据库。上面的每个数据库默认从 0 开始的递增数字命名。
因为该程序打包后的压缩包 >10 M,无法上传到 cnblogs,如有需要的童鞋请加群在群文件中下载压缩包。
补充一下园友(心态要好)推荐的其它 GUI 工具 RedisDeskTopManager:https://redisdesktop.com/download。
C# 驱动
之前在 《使用 StackExchange.Redis 封装属于自己的 RedisHelper》 曾经发布了一篇使用 StackExchange.Redis 进行了简单封装的 RedisHelper,你可以选择查看之前的文章,从中借鉴一些思想或者给出一些建议。
这里是更新后的 Helper 代码(直接展开即可),代码的后续更新在 GitHub 上。
1 #region 2 3 using System; 4 using System.Collections.Generic; 5 using System.Configuration; 6 using System.IO; 7 using System.Linq; 8 using System.Runtime.Serialization.Formatters.Binary; 9 using System.Threading.Tasks; 10 using StackExchange.Redis; 11 12 #endregion 13 14 namespace Wen.Helpers.Common.Redis 15 { 16 /// <summary> 17 /// Redis 助手 18 /// </summary> 19 public class RedisHelper 20 { 21 /// <summary> 22 /// 获取 Redis 连接对象 23 /// </summary> 24 /// <returns></returns> 25 public IConnectionMultiplexer GetConnectionRedisMultiplexer() 26 { 27 if (_connMultiplexer == null || !_connMultiplexer.IsConnected) 28 lock (Locker) 29 { 30 if (_connMultiplexer == null || !_connMultiplexer.IsConnected) 31 _connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString); 32 } 33 34 return _connMultiplexer; 35 } 36 37 #region 其它 38 39 public ITransaction GetTransaction() 40 { 41 return _db.CreateTransaction(); 42 } 43 44 #endregion 其它 45 46 #region private field 47 48 /// <summary> 49 /// 连接字符串 50 /// </summary> 51 private static readonly string ConnectionString; 52 53 /// <summary> 54 /// redis 连接对象 55 /// </summary> 56 private static IConnectionMultiplexer _connMultiplexer; 57 58 /// <summary> 59 /// 默认的 Key 值(用来当作 RedisKey 的前缀) 60 /// </summary> 61 private static readonly string DefaultKey; 62 63 /// <summary> 64 /// 锁 65 /// </summary> 66 private static readonly object Locker = new object(); 67 68 /// <summary> 69 /// 数据库 70 /// </summary> 71 private readonly IDatabase _db; 72 73 #endregion private field 74 75 #region 构造函数 76 77 static RedisHelper() 78 { 79 ConnectionString = ConfigurationManager.ConnectionStrings["RedisConnectionString"].ConnectionString; 80 _connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString); 81 DefaultKey = ConfigurationManager.AppSettings["Redis.DefaultKey"]; 82 AddRegisterEvent(); 83 } 84 85 public RedisHelper(int db = 0) 86 { 87 _db = _connMultiplexer.GetDatabase(db); 88 } 89 90 #endregion 构造函数 91 92 #region String 操作 93 94 /// <summary> 95 /// 设置 key 并保存字符串(如果 key 已存在,则覆盖值) 96 /// </summary> 97 /// <param name="key"></param> 98 /// <param name="value"></param> 99 /// <param name="expiry"></param> 100 /// <returns></returns> 101 public bool StringSet(string key, string value, TimeSpan? expiry = null) 102 { 103 key = AddKeyPrefix(key); 104 return _db.StringSet(key, value, expiry); 105 } 106 107 /// <summary> 108 /// 保存多个 Key-value 109 /// </summary> 110 /// <param name="keyValuePairs"></param> 111 /// <returns></returns> 112 public bool StringSet(IEnumerable<KeyValuePair<string, string>> keyValuePairs) 113 { 114 var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value)); 115 return _db.StringSet(pairs.ToArray()); 116 } 117 118 /// <summary> 119 /// 获取字符串 120 /// </summary> 121 /// <param name="redisKey"></param> 122 /// <param name="expiry"></param> 123 /// <returns></returns> 124 public string StringGet(string redisKey) 125 { 126 redisKey = AddKeyPrefix(redisKey); 127 return _db.StringGet(redisKey); 128 } 129 130 /// <summary> 131 /// 存储一个对象(该对象会被序列化保存) 132 /// </summary> 133 /// <param name="key"></param> 134 /// <param name="value"></param> 135 /// <param name="expiry"></param> 136 /// <returns></returns> 137 public bool StringSet<T>(string key, T value, TimeSpan? expiry = null) 138 { 139 key = AddKeyPrefix(key); 140 var json = Serialize(value); 141 142 return _db.StringSet(key, json, expiry); 143 } 144 145 /// <summary> 146 /// 获取一个对象(会进行反序列化) 147 /// </summary> 148 /// <param name="key"></param> 149 /// <param name="expiry"></param> 150 /// <returns></returns> 151 public T StringGet<T>(string key, TimeSpan? expiry = null) 152 { 153 key = AddKeyPrefix(key); 154 return Deserialize<T>(_db.StringGet(key)); 155 } 156 157 /// <summary> 158 /// 在指定 key 处实现增量的递增,如果该键不存在,则在执行前将其设置为 0 159 /// </summary> 160 /// <param name="key"></param> 161 /// <param name="value"></param> 162 /// <returns></returns> 163 public double StringIncrement(string key, double value = 1) 164 { 165 key = AddKeyPrefix(key); 166 return _db.StringIncrement(key, value); 167 } 168 169 /// <summary> 170 /// 在指定 key 处实现增量的递减,如果该键不存在,则在执行前将其设置为 0 171 /// </summary> 172 /// <param name="key"></param> 173 /// <param name="value"></param> 174 /// <returns></returns> 175 public double StringDecrement(string key, double value = 1) 176 { 177 key = AddKeyPrefix(key); 178 return _db.StringDecrement(key, value); 179 } 180 181 #region async 182 183 /// <summary> 184 /// 保存一个字符串值 185 /// </summary> 186 /// <param name="key"></param> 187 /// <param name="value"></param> 188 /// <param name="expiry"></param> 189 /// <returns></returns> 190 public async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = null) 191 { 192 key = AddKeyPrefix(key); 193 return await _db.StringSetAsync(key, value, expiry); 194 } 195 196 /// <summary> 197 /// 保存一组字符串值 198 /// </summary> 199 /// <param name="keyValuePairs"></param> 200 /// <returns></returns> 201 public async Task<bool> StringSetAsync(IEnumerable<KeyValuePair<string, string>> keyValuePairs) 202 { 203 var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value)); 204 return await _db.StringSetAsync(pairs.ToArray()); 205 } 206 207 /// <summary> 208 /// 获取单个值 209 /// </summary> 210 /// <param name="key"></param> 211 /// <param name="value"></param> 212 /// <param name="expiry"></param> 213 /// <returns></returns> 214 public async Task<string> StringGetAsync(string key, string value, TimeSpan? expiry = null) 215 { 216 key = AddKeyPrefix(key); 217 return await _db.StringGetAsync(key); 218 } 219 220 /// <summary> 221 /// 存储一个对象(该对象会被序列化保存) 222 /// </summary> 223 /// <param name="key"></param> 224 /// <param name="value"></param> 225 /// <param name="expiry"></param> 226 /// <returns></returns> 227 public async Task<bool> StringSetAsync<T>(string key, T value, TimeSpan? expiry = null) 228 { 229 key = AddKeyPrefix(key); 230 var json = Serialize(value); 231 return await _db.StringSetAsync(key, json, expiry); 232 } 233 234 /// <summary> 235 /// 获取一个对象(会进行反序列化) 236 /// </summary> 237 /// <param name="key"></param> 238 /// <param name="expiry"></param> 239 /// <returns></returns> 240 public async Task<T> StringGetAsync<T>(string key, TimeSpan? expiry = null) 241 { 242 key = AddKeyPrefix(key); 243 return Deserialize<T>(await _db.StringGetAsync(key)); 244 } 245 246 /// <summary> 247 /// 在指定 key 处实现增量的递增,如果该键不存在,则在执行前将其设置为 0 248 /// </summary> 249 /// <param name="key"></param> 250 /// <param name="value"></param> 251 /// <returns></returns> 252 public async Task<double> StringIncrementAsync(string key, double value = 1) 253 { 254 key = AddKeyPrefix(key); 255 return await _db.StringIncrementAsync(key, value); 256 } 257 258 /// <summary> 259 /// 在指定 key 处实现增量的递减,如果该键不存在,则在执行前将其设置为 0 260 /// </summary> 261 /// <param name="key"></param> 262 /// <param name="value"></param> 263 /// <returns></returns> 264 public async Task<double> StringDecrementAsync(string key, double value = 1) 265 { 266 key = AddKeyPrefix(key); 267 return await _db.StringDecrementAsync(key, value); 268 } 269 270 #endregion async 271 272 #endregion String 操作 273 274 #region Hash 操作 275 276 /// <summary> 277 /// 判断该字段是否存在 hash 中 278 /// </summary> 279 /// <param name="key"></param> 280 /// <param name="hashField"></param> 281 /// <returns></returns> 282 public bool HashExists(string key, string hashField) 283 { 284 key = AddKeyPrefix(key); 285 return _db.HashExists(key, hashField); 286 } 287 288 /// <summary> 289 /// 从 hash 中移除指定字段 290 /// </summary> 291 /// <param name="key"></param> 292 /// <param name="hashField"></param> 293 /// <returns></returns> 294 public bool HashDelete(string key, string hashField) 295 { 296 key = AddKeyPrefix(key); 297 return _db.HashDelete(key, hashField); 298 } 299 300 /// <summary> 301 /// 从 hash 中移除指定字段 302 /// </summary> 303 /// <param name="key"></param> 304 /// <param name="hashFields"></param> 305 /// <returns></returns> 306 public long HashDelete(string key, IEnumerable<string> hashFields) 307 { 308 key = AddKeyPrefix(key); 309 var fields = hashFields.Select(x => (RedisValue) x); 310 311 return _db.HashDelete(key, fields.ToArray()); 312 } 313 314 /// <summary> 315 /// 在 hash 设定值 316 /// </summary> 317 /// <param name="key"></param> 318 /// <param name="hashField"></param> 319 /// <param name="value"></param> 320 /// <returns></returns> 321 public bool HashSet(string key, string hashField, string value) 322 { 323 key = AddKeyPrefix(key); 324 return _db.HashSet(key, hashField, value); 325 } 326 327 /// <summary> 328 /// 在 hash 中设定值 329 /// </summary> 330 /// <param name="key"></param> 331 /// <param name="hashFields"></param> 332 public void HashSet(string key, IEnumerable<KeyValuePair<string, string>> hashFields) 333 { 334 key = AddKeyPrefix(key); 335 var entries = hashFields.Select(x => new HashEntry(x.Key, x.Value)); 336 337 _db.HashSet(key, entries.ToArray()); 338 } 339 340 /// <summary> 341 /// 在 hash 中获取值 342 /// </summary> 343 /// <param name="key"></param> 344 /// <param name="hashField"></param> 345 /// <returns></returns> 346 public string HashGet(string key, string hashField) 347 { 348 key = AddKeyPrefix(key); 349 return _db.HashGet(key, hashField); 350 } 351 352 /// <summary> 353 /// 在 hash 中获取值 354 /// </summary> 355 /// <param name="key"></param> 356 /// <param name="hashFields"></param> 357 /// <returns></returns> 358 public IEnumerable<string> HashGet(string key, IEnumerable<string> hashFields) 359 { 360 key = AddKeyPrefix(key); 361 var fields = hashFields.Select(x => (RedisValue) x); 362 363 return ConvertStrings(_db.HashGet(key, fields.ToArray())); 364 } 365 366 /// <summary> 367 /// 从 hash 返回所有的字段值 368 /// </summary> 369 /// <param name="key"></param> 370 /// <returns></returns> 371 public IEnumerable<string> HashKeys(string key) 372 { 373 key = AddKeyPrefix(key); 374 return ConvertStrings(_db.HashKeys(key)); 375 } 376 377 /// <summary> 378 /// 返回 hash 中的所有值 379 /// </summary> 380 /// <param name="key"></param> 381 /// <returns></returns> 382 public IEnumerable<string> HashValues(string key) 383 { 384 key = AddKeyPrefix(key); 385 return ConvertStrings(_db.HashValues(key)); 386 } 387 388 /// <summary> 389 /// 在 hash 设定值(序列化) 390 /// </summary> 391 /// <param name="key"></param> 392 /// <param name="hashField"></param> 393 /// <param name="redisValue"></param> 394 /// <returns></returns> 395 public bool HashSet<T>(string key, string hashField, T redisValue) 396 { 397 key = AddKeyPrefix(key); 398 var json = Serialize(redisValue); 399 400 return _db.HashSet(key, hashField, json); 401 } 402 403 /// <summary> 404 /// 在 hash 中获取值(反序列化) 405 /// </summary> 406 /// <param name="key"></param> 407 /// <param name="hashField"></param> 408 /// <returns></returns> 409 public T HashGet<T>(string key, string hashField) 410 { 411 key = AddKeyPrefix(key); 412 return Deserialize<T>(_db.HashGet(key, hashField)); 413 } 414 415 /// <summary> 416 /// 指定键递增 417 /// </summary> 418 /// <param name="key"></param> 419 /// <param name="hashField"></param> 420 /// <param name="value"></param> 421 /// <returns></returns> 422 public double HashIncrement(string key, string hashField, double value = 1) 423 { 424 key = AddKeyPrefix(key); 425 return _db.HashIncrement(key, hashField, value); 426 } 427 428 /// <summary> 429 /// 指定键递减 430 /// </summary> 431 /// <param name="key"></param> 432 /// <param name="hashField"></param> 433 /// <param name="value"></param> 434 /// <returns></returns> 435 public double HashDecrement(string key, string hashField, double value = 1) 436 { 437 key = AddKeyPrefix(key); 438 return _db.HashDecrement(key, hashField, value); 439 } 440 441 #region async 442 443 /// <summary> 444 /// 判断该字段是否存在 hash 中 445 /// </summary> 446 /// <param name="redisKey"></param> 447 /// <param name="hashField"></param> 448 /// <returns></returns> 449 public async Task<bool> HashExistsAsync(string redisKey, string hashField) 450 { 451 redisKey = AddKeyPrefix(redisKey); 452 return await _db.HashExistsAsync(redisKey, hashField); 453 } 454 455 /// <summary> 456 /// 从 hash 中移除指定字段 457 /// </summary> 458 /// <param name="redisKey"></param> 459 /// <param name="hashField"></param> 460 /// <returns></returns> 461 public async Task<bool> HashDeleteAsync(string redisKey, string hashField) 462 { 463 redisKey = AddKeyPrefix(redisKey); 464 return await _db.HashDeleteAsync(redisKey, hashField); 465 } 466 467 /// <summary> 468 /// 从 hash 中移除指定字段 469 /// </summary> 470 /// <param name="redisKey"></param> 471 /// <param name="hashFields"></param> 472 /// <returns></returns> 473 public async Task<long> HashDeleteAsync(string redisKey, IEnumerable<string> hashFields) 474 { 475 redisKey = AddKeyPrefix(redisKey); 476 var fields = hashFields.Select(x => (RedisValue) x); 477 478 return await _db.HashDeleteAsync(redisKey, fields.ToArray()); 479 } 480 481 /// <summary> 482 /// 在 hash 设定值 483 /// </summary> 484 /// <param name="redisKey"></param> 485 /// <param name="hashField"></param> 486 /// <param name="value"></param> 487 /// <returns></returns> 488 public async Task<bool> HashSetAsync(string redisKey, string hashField, string value) 489 { 490 redisKey = AddKeyPrefix(redisKey); 491 return await _db.HashSetAsync(redisKey, hashField, value); 492 } 493 494 /// <summary> 495 /// 在 hash 中设定值 496 /// </summary> 497 /// <param name="redisKey"></param> 498 /// <param name="hashFields"></param> 499 public async Task HashSetAsync(string redisKey, IEnumerable<KeyValuePair<string, string>> hashFields) 500 { 501 redisKey = AddKeyPrefix(redisKey); 502 var entries = hashFields.Select(x => new HashEntry(AddKeyPrefix(x.Key), x.Value)); 503 await _db.HashSetAsync(redisKey, entries.ToArray()); 504 } 505 506 /// <summary> 507 /// 在 hash 中获取值 508 /// </summary> 509 /// <param name="redisKey"></param> 510 /// <param name="hashField"></param> 511 /// <returns></returns> 512 public async Task<string> HashGetAsync(string redisKey, string hashField) 513 { 514 redisKey = AddKeyPrefix(redisKey); 515 return await _db.HashGetAsync(redisKey, hashField); 516 } 517 518 /// <summary> 519 /// 在 hash 中获取值 520 /// </summary> 521 /// <param name="redisKey"></param> 522 /// <param name="hashFields"></param> 523 /// <param name="value"></param> 524 /// <returns></returns> 525 public async Task<IEnumerable<string>> HashGetAsync(string redisKey, IEnumerable<string> hashFields, 526 string value) 527 { 528 redisKey = AddKeyPrefix(redisKey); 529 var fields = hashFields.Select(x => (RedisValue) x); 530 531 return ConvertStrings(await _db.HashGetAsync(redisKey, fields.ToArray())); 532 } 533 534 /// <summary> 535 /// 从 hash 返回所有的字段值 536 /// </summary> 537 /// <param name="redisKey"></param> 538 /// <returns></returns> 539 public async Task<IEnumerable<string>> HashKeysAsync(string redisKey) 540 { 541 redisKey = AddKeyPrefix(redisKey); 542 return ConvertStrings(await _db.HashKeysAsync(redisKey)); 543 } 544 545 /// <summary> 546 /// 返回 hash 中的所有值 547 /// </summary> 548 /// <param name="redisKey"></param> 549 /// <returns></returns> 550 public async Task<IEnumerable<string>> HashValuesAsync(string redisKey) 551 { 552 redisKey = AddKeyPrefix(redisKey); 553 return ConvertStrings(await _db.HashValuesAsync(redisKey)); 554 } 555 556 /// <summary> 557 /// 在 hash 设定值(序列化) 558 /// </summary> 559 /// <param name="redisKey"></param> 560 /// <param name="hashField"></param> 561 /// <param name="value"></param> 562 /// <returns></returns> 563 public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value) 564 { 565 redisKey = AddKeyPrefix(redisKey); 566 var json = Serialize(value); 567 return await _db.HashSetAsync(redisKey, hashField, json); 568 } 569 570 /// <summary> 571 /// 在 hash 中获取值(反序列化) 572 /// </summary> 573 /// <param name="redisKey"></param> 574 /// <param name="hashField"></param> 575 /// <returns></returns> 576 public async Task<T> HashGetAsync<T>(string redisKey, string hashField) 577 { 578 redisKey = AddKeyPrefix(redisKey); 579 return Deserialize<T>(await _db.HashGetAsync(redisKey, hashField)); 580 } 581 582 /// <summary> 583 /// 指定键递增 584 /// </summary> 585 /// <param name="key"></param> 586 /// <param name="hashField"></param> 587 /// <param name="value"></param> 588 /// <returns></returns> 589 public async Task<double> HashIncrementAsync(string key, string hashField, double value = 1) 590 { 591 key = AddKeyPrefix(key); 592 return await _db.HashIncrementAsync(key, hashField, value); 593 } 594 595 /// <summary> 596 /// 指定键递减 597 /// </summary> 598 /// <param name="key"></param> 599 /// <param name="hashField"></param> 600 /// <param name="value"></param> 601 /// <returns></returns> 602 public async Task<double> HashDecrementAsync(string key, string hashField, double value = 1) 603 { 604 key = AddKeyPrefix(key); 605 return await _db.HashDecrementAsync(key, hashField, value); 606 } 607 608 #endregion async 609 610 #endregion Hash 操作 611 612 #region List 操作 613 614 /// <summary> 615 /// 移除并返回存储在该键列表的第一个元素 616 /// </summary> 617 /// <param name="key"></param> 618 /// <returns></returns> 619 public string ListLeftPop(string key) 620 { 621 key = AddKeyPrefix(key); 622 return _db.ListLeftPop(key); 623 } 624 625 /// <summary> 626 /// 出列,移除并返回存储在该键列表的最后一个元素 627 /// </summary> 628 /// <param name="key"></param> 629 /// <returns></returns> 630 public string ListRightPop(string key) 631 { 632 key = AddKeyPrefix(key); 633 return _db.ListRightPop(key); 634 } 635 636 /// <summary> 637 /// 移除列表指定键上与该值相同的元素 638 /// </summary> 639 /// <param name="key"></param> 640 /// <param name="value"></param> 641 /// <returns></returns> 642 public long ListRemove(string key, string value) 643 { 644 key = AddKeyPrefix(key); 645 return _db.ListRemove(key, value); 646 } 647 648 /// <summary> 649 /// 入列,在列表尾部插入值。如果键不存在,先创建再插入值 650 /// </summary> 651 /// <param name="key"></param> 652 /// <param name="value"></param> 653 /// <returns></returns> 654 public long ListRightPush(string key, string value) 655 { 656 key = AddKeyPrefix(key); 657 return _db.ListRightPush(key, value); 658 } 659 660 /// <summary> 661 /// 在列表头部插入值。如果键不存在,先创建再插入值 662 /// </summary> 663 /// <param name="key"></param> 664 /// <param name="value"></param> 665 /// <returns></returns> 666 public long ListLeftPush(string key, string value) 667 { 668 key = AddKeyPrefix(key); 669 return _db.ListLeftPush(key, value); 670 } 671 672 /// <summary> 673 /// 返回列表上该键的长度,如果不存在,返回 0 674 /// </summary> 675 /// <param name="key"></param> 676 /// <returns></returns> 677 public long ListLength(string key) 678 { 679 key = AddKeyPrefix(key); 680 return _db.ListLength(key); 681 } 682 683 /// <summary> 684 /// 返回在该列表上键所对应的元素 685 /// </summary> 686 /// <param name="key"></param> 687 /// <param name="start"></param> 688 /// <param name="stop"></param> 689 /// <returns></returns> 690 public IEnumerable<string> ListRange(string key, long start = 0L, long stop = -1L) 691 { 692 key = AddKeyPrefix(key); 693 return ConvertStrings(_db.ListRange(key, start, stop)); 694 } 695 696 /// <summary> 697 /// 移除并返回存储在该键列表的第一个元素 698 /// </summary> 699 /// <param name="key"></param> 700 /// <returns></returns> 701 public T ListLeftPop<T>(string key) 702 { 703 key = AddKeyPrefix(key); 704 return Deserialize<T>(_db.ListLeftPop(key)); 705 } 706 707 /// <summary> 708 /// 出队,移除并返回存储在该键列表的最后一个元素 709 /// </summary> 710 /// <param name="key"></param> 711 /// <returns></returns> 712 public T ListRightPop<T>(string key) 713 { 714 key = AddKeyPrefix(key); 715 return Deserialize<T>(_db.ListRightPop(key)); 716 } 717 718 /// <summary> 719 /// 入队,在列表尾部插入值。如果键不存在,先创建再插入值 720 /// </summary> 721 /// <param name="key"></param> 722 /// <param name="value"></param> 723 /// <returns></returns> 724 public long ListRightPush<T>(string key, T value) 725 { 726 key = AddKeyPrefix(key); 727 return _db.ListRightPush(key, Serialize(value)); 728 } 729 730 /// <summary> 731 /// 在列表头部插入值。如果键不存在,先创建再插入值 732 /// </summary> 733 /// <param name="key"></param> 734 /// <param name="value"></param> 735 /// <returns></returns> 736 public long ListLeftPush<T>(string key, T value) 737 { 738 key = AddKeyPrefix(key); 739 return _db.ListLeftPush(key, Serialize(value)); 740 } 741 742 #region List-async 743 744 /// <summary> 745 /// 移除并返回存储在该键列表的第一个元素 746 /// </summary> 747 /// <param name="key"></param> 748 /// <returns></returns> 749 public async Task<string> ListLeftPopAsync(string key) 750 { 751 key = AddKeyPrefix(key); 752 return await _db.ListLeftPopAsync(key); 753 } 754 755 /// <summary> 756 /// 移除并返回存储在该键列表的最后一个元素 757 /// </summary> 758 /// <param name="key"></param> 759 /// <returns></returns> 760 public async Task<string> ListRightPopAsync(string key) 761 { 762 key = AddKeyPrefix(key); 763 return await _db.ListRightPopAsync(key); 764 } 765 766 /// <summary> 767 /// 移除列表指定键上与该值相同的元素 768 /// </summary> 769 /// <param name="key"></param> 770 /// <param name="value"></param> 771 /// <returns></returns> 772 public async Task<long> ListRemoveAsync(string key, string value) 773 { 774 key = AddKeyPrefix(key); 775 return await _db.ListRemoveAsync(key, value); 776 } 777 778 /// <summary> 779 /// 在列表尾部插入值。如果键不存在,先创建再插入值 780 /// </summary> 781 /// <param name="key"></param> 782 /// <param name="value"></param> 783 /// <returns></returns> 784 public async Task<long> ListRightPushAsync(string key, string value) 785 { 786 key = AddKeyPrefix(key); 787 return await _db.ListRightPushAsync(key, value); 788 } 789 790 /// <summary> 791 /// 在列表头部插入值。如果键不存在,先创建再插入值 792 /// </summary> 793 /// <param name="key"></param> 794 /// <param name="value"></param> 795 /// <returns></returns> 796 public async Task<long> ListLeftPushAsync(string key, string value) 797 { 798 key = AddKeyPrefix(key); 799 return await _db.ListLeftPushAsync(key, value); 800 } 801 802 /// <summary> 803 /// 返回列表上该键的长度,如果不存在,返回 0 804 /// </summary> 805 /// <param name="key"></param> 806 /// <returns></returns> 807 public async Task<long> ListLengthAsync(string key) 808 { 809 key = AddKeyPrefix(key); 810 return await _db.ListLengthAsync(key); 811 } 812 813 /// <summary> 814 /// 返回在该列表上键所对应的元素 815 /// </summary> 816 /// <param name="key"></param> 817 /// <param name="start"></param> 818 /// <param name="stop"></param> 819 /// <returns></returns> 820 public async Task<IEnumerable<string>> ListRangeAsync(string key, long start = 0L, long stop = -1L) 821 { 822 key = AddKeyPrefix(key); 823 var query = await _db.ListRangeAsync(key, start, stop); 824 return query.Select(x => x.ToString()); 825 } 826 827 /// <summary> 828 /// 移除并返回存储在该键列表的第一个元素 829 /// </summary> 830 /// <param name="key"></param> 831 /// <returns></returns> 832 public async Task<T> ListLeftPopAsync<T>(string key) 833 { 834 key = AddKeyPrefix(key); 835 return Deserialize<T>(await _db.ListLeftPopAsync(key)); 836 } 837 838 /// <summary> 839 /// 移除并返回存储在该键列表的最后一个元素 840 /// </summary> 841 /// <param name="key"></param> 842 /// <returns></returns> 843 public async Task<T> ListRightPopAsync<T>(string key) 844 { 845 key = AddKeyPrefix(key); 846 return Deserialize<T>(await _db.ListRightPopAsync(key)); 847 } 848 849 /// <summary> 850 /// 在列表尾部插入值。如果键不存在,先创建再插入值 851 /// </summary> 852 /// <param name="key"></param> 853 /// <param name="value"></param> 854 /// <returns></returns> 855 public async Task<long> ListRightPushAsync<T>(string key, T value) 856 { 857 key = AddKeyPrefix(key); 858 return await _db.ListRightPushAsync(key, Serialize(value)); 859 } 860 861 /// <summary> 862 /// 在列表头部插入值。如果键不存在,先创建再插入值 863 /// </summary> 864 /// <param name="key"></param> 865 /// <param name="value"></param> 866 /// <returns></returns> 867 public async Task<long> ListLeftPushAsync<T>(string key, T value) 868 { 869 key = AddKeyPrefix(key); 870 return await _db.ListLeftPushAsync(key, Serialize(value)); 871 } 872 873 #endregion List-async 874 875 #endregion List 操作 876 877 #region SortedSet 操作 878 879 /// <summary> 880 /// SortedSet 新增 881 /// </summary> 882 /// <param name="key"></param> 883 /// <param name="member"></param> 884 /// <param name="score"></param> 885 /// <returns></returns> 886 public bool SortedSetAdd(string key, string member, double score) 887 { 888 key = AddKeyPrefix(key); 889 return _db.SortedSetAdd(key, member, score); 890 } 891 892 /// <summary> 893 /// 在有序集合中返回指定范围的元素,默认情况下从低到高。 894 /// </summary> 895 /// <param name="key"></param> 896 /// <param name="start"></param> 897 /// <param name="stop"></param> 898 /// <param name="order"></param> 899 /// <returns></returns> 900 public IEnumerable<string> SortedSetRangeByRank(string key, long start = 0L, long stop = -1L, 901 OrderType order = OrderType.Ascending) 902 { 903 key = AddKeyPrefix(key); 904 return _db.SortedSetRangeByRank(key, start, stop, (Order) order).Select(x => x.ToString()); 905 } 906 907 /// <summary> 908 /// 返回有序集合的元素个数 909 /// </summary> 910 /// <param name="key"></param> 911 /// <returns></returns> 912 public long SortedSetLength(string key) 913 { 914 key = AddKeyPrefix(key); 915 return _db.SortedSetLength(key); 916 } 917 918 /// <summary> 919 /// 返回有序集合的元素个数 920 /// </summary> 921 /// <param name="key"></param> 922 /// <param name="memebr"></param> 923 /// <returns></returns> 924 public bool SortedSetRemove(string key, string memebr) 925 { 926 key = AddKeyPrefix(key); 927 return _db.SortedSetRemove(key, memebr); 928 } 929 930 /// <summary> 931 /// SortedSet 新增 932 /// </summary> 933 /// <param name="key"></param> 934 /// <param name="member"></param> 935 /// <param name="score"></param> 936 /// <returns></returns> 937 public bool SortedSetAdd<T>(string key, T member, double score) 938 { 939 key = AddKeyPrefix(key); 940 var json = Serialize(member); 941 942 return _db.SortedSetAdd(key, json, score); 943 } 944 945 /// <summary> 946 /// 增量的得分排序的集合中的成员存储键值键按增量 947 /// </summary> 948 /// <param name="key"></param> 949 /// <param name="member"></param> 950 /// <param name="value"></param> 951 /// <returns></returns> 952 public double SortedSetIncrement(string key, string member, double value = 1) 953 { 954 key = AddKeyPrefix(key); 955 return _db.SortedSetIncrement(key, member, value); 956 } 957 958 #region SortedSet-Async 959 960 /// <summary> 961 /// SortedSet 新增 962 /// </summary> 963 /// <param name="key"></param> 964 /// <param name="member"></param> 965 /// <param name="score"></param> 966 /// <returns></returns> 967 public async Task<bool> SortedSetAddAsync(string key, string member, double score) 968 { 969 key = AddKeyPrefix(key); 970 return await _db.SortedSetAddAsync(key, member, score); 971 } 972 973 /// <summary> 974 /// 在有序集合中返回指定范围的元素,默认情况下从低到高。 975 /// </summary> 976 /// <param name="key"></param> 977 /// <returns></returns> 978 public async Task<IEnumerable<string>> SortedSetRangeByRankAsync(string key) 979 { 980 key = AddKeyPrefix(key); 981 return ConvertStrings(await _db.SortedSetRangeByRankAsync(key)); 982 } 983 984 /// <summary> 985 /// 返回有序集合的元素个数 986 /// </summary> 987 /// <param name="key"></param> 988 /// <returns></returns> 989 public async Task<long> SortedSetLengthAsync(string key) 990 { 991 key = AddKeyPrefix(key); 992 return await _db.SortedSetLengthAsync(key); 993 } 994 995 /// <summary> 996 /// 返回有序集合的元素个数 997 /// </summary> 998 /// <param name="key"></param> 999 /// <param name="memebr"></param>1000 /// <returns></returns>1001 public async Task<bool> SortedSetRemoveAsync(string key, string memebr)1002 {1003 key = AddKeyPrefix(key);1004 return await _db.SortedSetRemoveAsync(key, memebr);1005 }1006 1007 /// <summary>1008 /// SortedSet 新增1009 /// </summary>1010 /// <param name="key"></param>1011 /// <param name="member"></param>1012 /// <param name="score"></param>1013 /// <returns></returns>1014 public async Task<bool> SortedSetAddAsync<T>(string key, T member, double score)1015 {1016 key = AddKeyPrefix(key);1017 var json = Serialize(member);1018 1019 return await _db.SortedSetAddAsync(key, json, score);1020 }1021 1022 /// <summary>1023 /// 增量的得分排序的集合中的成员存储键值键按增量1024 /// </summary>1025 /// <param name="key"></param>1026 /// <param name="member"></param>1027 /// <param name="value"></param>1028 /// <returns></returns>1029 public Task<double> SortedSetIncrementAsync(string key, string member, double value = 1)1030 {1031 key = AddKeyPrefix(key);1032 return _db.SortedSetIncrementAsync(key, member, value);1033 }1034 1035 #endregion SortedSet-Async1036 1037 #endregion SortedSet 操作1038 1039 #region key 操作1040 1041 /// <summary>1042 /// 移除指定 Key1043 /// </summary>1044 /// <param name="key"></param>1045 /// <returns></returns>1046 public bool KeyDelete(string key)1047 {1048 key = AddKeyPrefix(key);1049 return _db.KeyDelete(key);1050 }1051 1052 /// <summary>1053 /// 移除指定 Key1054 /// </summary>1055 /// <param name="keys"></param>1056 /// <returns></returns>1057 public long KeyDelete(IEnumerable<string> keys)1058 {1059 var redisKeys = keys.Select(x => (RedisKey) AddKeyPrefix(x));1060 return _db.KeyDelete(redisKeys.ToArray());1061 }1062 1063 /// <summary>1064 /// 校验 Key 是否存在1065 /// </summary>1066 /// <param name="key"></param>1067 /// <returns></returns>1068 public bool KeyExists(string key)1069 {1070 key = AddKeyPrefix(key);1071 return _db.KeyExists(key);1072 }1073 1074 /// <summary>1075 /// 重命名 Key1076 /// </summary>1077 /// <param name="key"></param>1078 /// <param name="newKey"></param>1079 /// <returns></returns>1080 public bool KeyRename(string key, string newKey)1081 {1082 key = AddKeyPrefix(key);1083 return _db.KeyRename(key, newKey);1084 }1085 1086 /// <summary>1087 /// 设置 Key 的时间1088 /// </summary>1089 /// <param name="key"></param>1090 /// <param name="expiry"></param>1091 /// <returns></returns>1092 public bool KeyExpire(string key, TimeSpan? expiry)1093 {1094 key = AddKeyPrefix(key);1095 return _db.KeyExpire(key, expiry);1096 }1097 1098 #region key-async1099 1100 /// <summary>1101 /// 移除指定 Key1102 /// </summary>1103 /// <param name="key"></param>1104 /// <returns></returns>1105 public async Task<bool> KeyDeleteAsync(string key)1106 {1107 key = AddKeyPrefix(key);1108 return await _db.KeyDeleteAsync(key);1109 }1110 1111 /// <summary>1112 /// 移除指定 Key1113 /// </summary>1114 /// <param name="keys"></param>1115 /// <returns></returns>1116 public async Task<long> KeyDeleteAsync(IEnumerable<string> keys)1117 {1118 var redisKeys = keys.Select(x => (RedisKey) AddKeyPrefix(x));1119 return await _db.KeyDeleteAsync(redisKeys.ToArray());1120 }1121 1122 /// <summary>1123 /// 校验 Key 是否存在1124 /// </summary>1125 /// <param name="key"></param>1126 /// <returns></returns>1127 public async Task<bool> KeyExistsAsync(string key)1128 {1129 key = AddKeyPrefix(key);1130 return await _db.KeyExistsAsync(key);1131 }1132 1133 /// <summary>1134 /// 重命名 Key1135 /// </summary>1136 /// <param name="key"></param>1137 /// <param name="newKey"></param>1138 /// <returns></returns>1139 public async Task<bool> KeyRenameAsync(string key, string newKey)1140 {1141 key = AddKeyPrefix(key);1142 return await _db.KeyRenameAsync(key, newKey);1143 }1144 1145 /// <summary>1146 /// 设置 Key 的时间1147 /// </summary>1148 /// <param name="key"></param>1149 /// <param name="expiry"></param>1150 /// <returns></returns>1151 public async Task<bool> KeyExpireAsync(string key, TimeSpan? expiry)1152 {1153 key = AddKeyPrefix(key);1154 return await _db.KeyExpireAsync(key, expiry);1155 }1156 1157 #endregion key-async1158 1159 #endregion key 操作1160 1161 #region 发布订阅1162 1163 /// <summary>1164 /// 订阅1165 /// </summary>1166 /// <param name="channel"></param>1167 /// <param name="handle"></param>1168 public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle)1169 {1170 var sub = _connMultiplexer.GetSubscriber();1171 sub.Subscribe(channel, handle);1172 }1173 1174 /// <summary>1175 /// 发布1176 /// </summary>1177 /// <param name="channel"></param>1178 /// <param name="message"></param>1179 /// <returns></returns>1180 public long Publish(RedisChannel channel, RedisValue message)1181 {1182 var sub = _connMultiplexer.GetSubscriber();1183 return sub.Publish(channel, message);1184 }1185 1186 /// <summary>1187 /// 发布(使用序列化)1188 /// </summary>1189 /// <typeparam name="T"></typeparam>1190 /// <param name="channel"></param>1191 /// <param name="message"></param>1192 /// <returns></returns>1193 public long Publish<T>(RedisChannel channel, T message)1194 {1195 var sub = _connMultiplexer.GetSubscriber();1196 return sub.Publish(channel, Serialize(message));1197 }1198 1199 #region 发布订阅-async1200 1201 /// <summary>1202 /// 订阅1203 /// </summary>1204 /// <param name="channel"></param>1205 /// <param name="handle"></param>1206 public async Task SubscribeAsync(RedisChannel channel, Action<RedisChannel, RedisValue> handle)1207 {1208 var sub = _connMultiplexer.GetSubscriber();1209 await sub.SubscribeAsync(channel, handle);1210 }1211 1212 /// <summary>1213 /// 发布1214 /// </summary>1215 /// <param name="channel"></param>1216 /// <param name="message"></param>1217 /// <returns></returns>1218 public async Task<long> PublishAsync(RedisChannel channel, RedisValue message)1219 {1220 var sub = _connMultiplexer.GetSubscriber();1221 return await sub.PublishAsync(channel, message);1222 }1223 1224 /// <summary>1225 /// 发布(使用序列化)1226 /// </summary>1227 /// <typeparam name="T"></typeparam>1228 /// <param name="channel"></param>1229 /// <param name="message"></param>1230 /// <returns></returns>1231 public async Task<long> PublishAsync<T>(RedisChannel channel, T message)1232 {1233 var sub = _connMultiplexer.GetSubscriber();1234 return await sub.PublishAsync(channel, Serialize(message));1235 }1236 1237 #endregion 发布订阅-async1238 1239 #endregion 发布订阅1240 1241 #region private method1242 1243 /// <summary>1244 /// 添加 Key 的前缀1245 /// </summary>1246 /// <param name="key"></param>1247 /// <returns></returns>1248 private static string AddKeyPrefix(string key)1249 {1250 return $"{DefaultKey}:{key}";1251 }1252 1253 /// <summary>1254 /// 转换为字符串1255 /// </summary>1256 /// <typeparam name="T"></typeparam>1257 /// <param name="list"></param>1258 /// <returns></returns>1259 private static IEnumerable<string> ConvertStrings<T>(IEnumerable<T> list) where T : struct1260 {1261 if (list == null) throw new ArgumentNullException(nameof(list));1262 return list.Select(x => x.ToString());1263 }1264 1265 #region 注册事件1266 1267 /// <summary>1268 /// 添加注册事件1269 /// </summary>1270 private static void AddRegisterEvent()1271 {1272 _connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;1273 _connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;1274 _connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;1275 _connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;1276 _connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;1277 _connMultiplexer.InternalError += ConnMultiplexer_InternalError;1278 _connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;1279 }1280 1281 /// <summary>1282 /// 重新配置广播时(通常意味着主从同步更改)1283 /// </summary>1284 /// <param name="sender"></param>1285 /// <param name="e"></param>1286 private static void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)1287 {1288 Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");1289 }1290 1291 /// <summary>1292 /// 发生内部错误时(主要用于调试)1293 /// </summary>1294 /// <param name="sender"></param>1295 /// <param name="e"></param>1296 private static void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)1297 {1298 Console.WriteLine($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");1299 }1300 1301 /// <summary>1302 /// 更改集群时1303 /// </summary>1304 /// <param name="sender"></param>1305 /// <param name="e"></param>1306 private static void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)1307 {1308 Console.WriteLine(1309 $"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");1310 }1311 1312 /// <summary>1313 /// 配置更改时1314 /// </summary>1315 /// <param name="sender"></param>1316 /// <param name="e"></param>1317 private static void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)1318 {1319 Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");1320 }1321 1322 /// <summary>1323 /// 发生错误时1324 /// </summary>1325 /// <param name="sender"></param>1326 /// <param name="e"></param>1327 private static void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)1328 {1329 Console.WriteLine($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");1330 }1331 1332 /// <summary>1333 /// 物理连接失败时1334 /// </summary>1335 /// <param name="sender"></param>1336 /// <param name="e"></param>1337 private static void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)1338 {1339 Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");1340 }1341 1342 /// <summary>1343 /// 建立物理连接时1344 /// </summary>1345 /// <param name="sender"></param>1346 /// <param name="e"></param>1347 private static void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)1348 {1349 Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");1350 }1351 1352 #endregion 注册事件1353 1354 /// <summary>1355 /// 序列化1356 /// </summary>1357 /// <param name="obj"></param>1358 /// <returns></returns>1359 private static byte[] Serialize(object obj)1360 {1361 if (obj == null)1362 return null;1363 1364 var binaryFormatter = new BinaryFormatter();1365 using (var memoryStream = new MemoryStream())1366 {1367 binaryFormatter.Serialize(memoryStream, obj);1368 var data = memoryStream.ToArray();1369 return data;1370 }1371 }1372 1373 /// <summary>1374 /// 反序列化1375 /// </summary>1376 /// <typeparam name="T"></typeparam>1377 /// <param name="data"></param>1378 /// <returns></returns>1379 private static T Deserialize<T>(byte[] data)1380 {1381 if (data == null)1382 return default(T);1383 1384 var binaryFormatter = new BinaryFormatter();1385 using (var memoryStream = new MemoryStream(data))1386 {1387 var result = (T) binaryFormatter.Deserialize(memoryStream);1388 return result;1389 }1390 }1391 1392 #endregion private method1393 }1394 }
RedisHelper.cs
下期将分析 redis 的五大类型,及介绍他们常用的指令。
系列
《Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍》
《Redis 小白指南(二)- 聊聊五大类型:字符串、散列、列表、集合和有序集合》
《Redis 小白指南(三)- 事务、过期、消息通知、管道、优化内存空间》
【博主】反骨仔
【原文】http://www.cnblogs.com/liqingwen/p/6917426.html
【GitHub】https://github.com/liqingwen2015/Wen.Helpers/blob/master/Wen.Helpers.Common/Redis/RedisHelper.cs
【参考】《redis 入门指南》
评论前必须登录!
立即登录