一个Redis client发布消息,其他多个redis client订阅消息,发布的消息“即发即失”,redis不会持久保存发布的消息;消息订阅者也将只能得到订阅之后的消息,通道中此前的消息将无从获得。 消息发布者,即publish客户端,...

一个Redis client发布消息,其他多个redis client订阅消息,发布的消息“即发即失”,redis不会持久保存发布的消息;消息订阅者也将只能得到订阅之后的消息,通道中此前的消息将无从获得。
消息发布者,即publish客户端,无需独占链接,你可以在publish消息的同时,使用同一个redis-client链接进行其他操作(例如:INCR等)
消息订阅者,即subscribe客户端,需要独占链接,即进行subscribe期间,redis-client无法穿插其他操作,
此时client以阻塞的方式等待“publish端”的消息;因此这里subscribe端需要使用单独的链接,甚至需要在额外的线程中使用。
Tcp默认连接时间固定,如果在这时间内sub端没有接收到pub端消息,或pub端没有消息产生,sub端的连接都会被强制回收,
这里就需要使用特殊手段解决,用定时器来模拟pub和sub之间的保活机制,定时器时间不能超过TCP最大连接时间,具体根据机器环境来定;
一旦subscribe端断开链接,将会失去部分消息,即链接失效期间的消息将会丢失,所以这里就需要考虑到借助redis的list来持久化;
总结:pub发布的消息不会持久化,sub是阻塞等待消息,只能获取订阅之后的产生的消息,一段时间内sub没有收到消息或pub没有生产消息,sub连接会被回收(因为sub是阻塞的).
如果你非常关注每个消息,那么你应该基于Redis做一些额外的补充工作,如果你期望订阅是持久的,那么如下的设计思路可以借鉴:
1) subscribe端:
首先向一个Set集合中增加“订阅者ID”, 此Set集合保存了“活跃订阅”者,订阅者ID标记每个唯一的订阅者,此Set为 "活跃订阅者集合"
2) subcribe端开启订阅操作,并基于Redis创建一个以 "订阅者ID" 为KEY的LIST数据结构,此LIST中存储了所有的尚未消费的消息,此List称为 "订阅者消息队列"
3) publish端:
每发布一条消息之后,publish端都需要遍历 "活跃订阅者集合",并依次向每个 "订阅者消息队列" 尾部追加此次发布的消息.
4) 到此为止,我们可以基本保证,发布的每一条消息,都会持久保存在每个 "订阅者消息队列" 中.
5) subscribe端,每收到一个订阅消息,在消费之后,必须删除自己的 "订阅者消息队列" 头部的一条记录.
6) subscribe端启动时,如果发现自己的 "订阅者消息队列" 有残存记录, 那么将会首先消费这些记录,然后再去订阅.
以上方法可以保证成功到达的消息必消费不丢失;
本文标题为:redis的pub/sub机制


基础教程推荐
- SQL Server如何设置用户只能访问特定数据库和访问特定表或视图 2023-07-29
- Windows10系统中Oracle完全卸载正确步骤 2023-07-24
- redis乐观锁与悲观锁的实战 2023-07-13
- redis 数据库 2023-09-13
- Java程序员从笨鸟到菜鸟(五十三) 分布式之 Redis 2023-09-11
- Python安装第三方库的方法(pip/conda、easy_install、setup.py) 2023-07-28
- Mariadb数据库主从复制同步配置过程实例 2023-07-25
- Python常见库matplotlib学习笔记之画图中各个模块的含义及修改方法 2023-07-27
- oracle数据库排序后如何获取第一条数据 2023-07-24
- oracle19c卸载教程的超详细教程 2023-07-23