很是感谢依乐祝发表文章《.NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐》,对csredis做了一次完整的诠释。html
提到消息队列,最熟悉无疑是 rabbitmq,它基本是业界标准的解决方案。本文详细介绍 redis 多种实现轻订阅方法,做者认为很是有趣并加以总结,但愿对有须要的朋友学习 redis 功能有必定的带入做用。git
//程序1:使用代码实现订阅端 var sub = RedisHelper.Subscribe(("chan1", msg => Console.WriteLine(msg.Body))); //sub.Disponse(); //中止订阅 //程序2:使用代码实现发布端 RedisHelper.Publish("chan1", "111");
优点:支持多端订阅、简单、性能高;
缺点:数据会丢失;github
参考资料:http://doc.redisfans.com/pub_sub/subscribe.htmlredis
//程序1:使用代码实现订阅端 while (running) { try { var msg = RedisHelper.BLPop(5, "list1"); if (string.IsNullOrEmpty(msg) == false) { Console.WriteLine(msg); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } //程序2:使用代码实现发布端 RedisHelper.LPush("list1", "111");
优点:数据不会丢失、简单、性能高;
缺点:不支持多端(存在资源争抢);shell
总结:为了解决方法一的痛点,咱们实现了本方法,而且很漂亮的制造了一个新问题(不支持多端订阅)。工具
BLPOP key [key ...] timeout性能
BLPOP 是列表的阻塞式(blocking)弹出原语。学习
它是 LPOP 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,链接将被 BLPOP 命令阻塞,直到等待超时或发现可弹出元素为止。测试
当给定多个 key 参数时,按参数 key 的前后顺序依次检查各个列表,弹出第一个非空列表的头元素。设计
当 BLPOP 被调用时,若是给定 key 内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字一块儿,组成结果返回给调用者。
当存在多个给定 key 时, BLPOP 按给定 key 参数排列的前后顺序,依次检查各个列表。
假设如今有 job 、 command 和 request 三个列表,其中 job 不存在, command 和 request 都持有非空列表。考虑如下命令:
BLPOP job command request 0
BLPOP 保证返回的元素来自 command ,由于它是按”查找 job -> 查找 command -> 查找 request “这样的顺序,第一个找到的非空列表。
redis> DEL job command request # 确保key都被删除 (integer) 0 redis> LPUSH command "update system..." # 为command列表增长一个值 (integer) 1 redis> LPUSH request "visit page" # 为request列表增长一个值 (integer) 1 redis> BLPOP job command request 0 # job 列表为空,被跳过,紧接着 command 列表的第一个元素被弹出。 1) "command" # 弹出元素所属的列表 2) "update system..." # 弹出元素所属的值
若是全部给定 key 都不存在或包含空列表,那么 BLPOP 命令将阻塞链接,直到等待超时,或有另外一个客户端对给定 key 的任意一个执行 LPUSH 或 RPUSH 命令为止。
超时参数 timeout 接受一个以秒为单位的数字做为值。超时参数设为 0 表示阻塞时间能够无限期延长(block indefinitely) 。
redis> EXISTS job # 确保两个 key 都不存在 (integer) 0 redis> EXISTS command (integer) 0 redis> BLPOP job command 300 # 由于key一开始不存在,因此操做会被阻塞,直到另外一客户端对 job 或者 command 列表进行 PUSH 操做。 1) "job" # 这里被 push 的是 job 2) "do my home work" # 被弹出的值 (26.26s) # 等待的秒数 redis> BLPOP job command 5 # 等待超时的状况 (nil) (5.66s) # 等待的秒数
更多学习资料:http://doc.redisfans.com/list/blpop.html
本方法根据方法二演变而来,设计图以下:
如何实现三端订阅,均可收到消息,三端分别为 sub3, sub4, sub5:
一、sub3, sub4, sub5 使用【方法二】订阅 listkey:list1_sub3,list1_sub4,list1_sub5;
二、总订阅端订阅 listkey:list1,总订阅端收到消息后,执行 lpush list1_sub1 msg, lpush list1_sub2 msg, lpush list1_sub3 msg;
总订阅端订阅原始消息,随后将消息分发给其余订阅端,从而解决【方法二】不支持多端同时订阅的缺点。
最终实现的逻辑为:多端先争抢 list1 消息,抢到者再向其余端转发消息。
nuget Install-Package CSRedisCore
var rds = new CSRedis.CSRedisClient("127.0.0.1:6379,password=,poolsize=50,ssl=false,writeBuffer=10240"); //sub1, sub2 争抢订阅(只可一端收到消息) var sub1 = rds.SubscribeList("list1", msg => Console.WriteLine($"sub1 -> list1 : {msg}")); var sub2 = rds.SubscribeList("list1", msg => Console.WriteLine($"sub2 -> list1 : {msg}")); //sub3, sub4, sub5 非争抢订阅(多端均可收到消息) var sub3 = rds.SubscribeListBroadcast("list2", "sub3", msg => Console.WriteLine($"sub3 -> list2 : {msg}")); var sub4 = rds.SubscribeListBroadcast("list2", "sub4", msg => Console.WriteLine($"sub4 -> list2 : {msg}")); var sub5 = rds.SubscribeListBroadcast("list2", "sub5", msg => Console.WriteLine($"sub5 -> list2 : {msg}")); //sub6 是redis自带的普通订阅 var sub6 = rds.Subscribe(("chan1", msg => Console.WriteLine(msg.Body))); Console.ReadKey(); sub1.Dispose(); sub2.Dispose(); sub3.Dispose(); sub4.Dispose(); sub5.Dispose(); sub6.Dispose(); rds.Dispose(); return;
测试功能时,发布端可使用 redis-cli 工具。
redis 功能何其多且至关好玩有趣 ,你们应尽量多带着兴趣爱好去学习它。
若文中有很差的地方,请提出批评与改正方法,谢谢观赏。
本文使用到 CSRedisCore 的开源地址:https://github.com/2881099/csredis