发布与订阅
-
Redis 发布订阅(pub/sub)是一种消息通信模式∶发送者(pub)发送消息,订阅者(sub)接收消息。实时聊天系统,实时视频播放系统,实时提醒,实时广播!Redis客户端可以订阅任意数量的频道。
-
核心便是发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息
-
当有新消息通过PUBLISH命令发送给频道channel1时,这个消息就会被发送给订阅它的三个客户端︰
-
Redis主要提供了发布消息、订阅频道、取消订阅以及按照模式订阅和取消订阅等命令
发布消息(publish)
PUBLISH <channel> <message>
- 当一个客户端执行PUBLISH命令的时候,会将消息message发送给频道channel
- 注意只能给一个管道推送一条信息
- 下面操作会向channel:sports频道发布一条消息“Tim won the championship”,返回结果为订阅者个数,因为此时没有订阅,所以返回结果为0
publish channel:sports "Tim won the championship"
订阅消息(subscribe)
subscribe channel [channel...]
- 订阅者可以订阅一个或多个频道
- 客户端在执行订阅命令之后进入了订阅状态,只能接收subscribe、 psubscribe、unsubscribe、punsubscribe的四个命令
- 新开启的订阅客户端,无法收到该频道之前的消息,因为Redis不会对发布的消息进行持久化
- 下面操作为当前客户端订阅了channel:sports频道:
subscribe channel:sports
- 此时右侧另一个客户端向channel:sports频道发布一条消息,右侧客户端会收到这条消息
- 和很多专业的消息队列系统(例如Kafka、RocketMQ)相比,Redis的发布订阅略显粗糙,例如无法实现消息堆积和回溯, 简单来说就是如果你是后续订阅的这个频道, 那这个频道前面推送的消息你是无法接受到的。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择
取消订阅(unsubscribe)
unsubscribe [channel [channel ...]]
- 客户端可以通过unsubscribe命令取消对指定频道的订阅,取消成功后, 不会再收到该频道的发布消息
- 取消订阅只对本个客户端有效,不会对其他客户端造成影响
发布-订阅的使用场景
- 聊天室、公告牌、服务之间利用消息解耦都可以使用发布订阅模式
- 下面以简单的服务解耦进行说明。如下图所示,图中有两套业务:
上面为视频管理系统,负责管理视频信息
下面为视频服务面向客户,用户可以通过各种客户端(手机、浏览器、接口)获取到视频信息
- 假如视频管理员在视频管理系统中对视频信息进行了变更,希望及时通知给视频服务端,就可以采用发布订阅的模式,发布视频信息变化的消息到指定频道,视频服务订阅这个频道及时更新视频信息,通过这种方式可以有效解决两个业务的耦合性
- 视频服务订阅video:changes频道如下:
subscribe video:changes
- 视频管理系统发布消息到video:changes频道如下:
publish video:changes "video1,video3,video5"
简述实现原理
- 通过subscribe命令订阅了某个频道之后, redis-server就会维护一个字典, 这个字典的键是频道的名字, value是一个链表, 链表中存储的是所有订阅这个频道的客户端, 所以subscribe的命令就是将我这个客户端加在对应频道的链表上
- 而通过publish命令向某个频道发布消息的时候就会在redis-server中的字典中找到这个频道对应的链表, 遍历链表, 将消息发送出去