本节概览:介绍redis pub/sub命令使用和原理。
本文内容来自 https://redisbook.readthedocs.io/en/latest/feature/pubsub.html
1 命令介绍
Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道, 每当有新信息发送到被订阅的频道时, 信息就会被发送给所有订阅指定频道的客户端。 发送的消息不会保存在Redis服务器里面,所以如果接收消息客户端断连,则会丢失消息。
1 2 3 4 |
127.0.0.1:6379> SUBSCRIBE channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "topic_test" |
下图展示了频道 channel1
, 以及订阅这个频道的三个客户端 client2
、 client5
和 client1
之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1
时, 这个消息就会被发送给订阅它的三个客户端:
命令举例
2 实现
2.1 数据结构
redis.h/redisServer
结构, 结构的 pubsub_channels
属性是一个字典, 这个字典就用于保存订阅频道的信息,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。
1 2 3 4 5 |
struct redisServer { // ... dict *pubsub_channels; // ... }; |
比如说,在下图展示的这个 pubsub_channels
示例中, client2
、 client5
和 client1
就订阅了 channel1
, 而其他频道也分别被别的客户端所订阅:
2.2 SUBSCRIBE
当客户端调用 SUBSCRIBE 命令时,程序就将客户端和要订阅的频道在 pubsub_channels
字典中关联起来。如客户端 client10086
执行命令 SUBSCRIBE channel1 channel2 channel3
,那么前面展示的 pubsub_channels
将变成下面这个样子:
伪代码如下
1 2 3 4 5 6 7 |
def SUBSCRIBE(client, channels): # 遍历所有输入频道 for channel in channels: # 将客户端添加到链表的末尾 redisServer.pubsub_channels[channel].append(client) |
2.3 PUBLISH命令
PUBLISH 命令的实现就非常简单了: 当调用 PUBLISH channel message
命令, 程序首先根据 channel
定位到字典的键, 然后将信息发送给字典值链表中的所有客户端。
比如说,对于以下这个 pubsub_channels
实例, 如果某个客户端执行命令 PUBLISH channel1 "hello moto"
,那么 client2
、 client5
和 client1
三个客户端都将接收到 "hello moto"
信息。
伪代码如下
1 2 3 4 5 6 7 |
def PUBLISH(channel, message): # 遍历所有订阅频道 channel 的客户端 for client in server.pubsub_channels[channel]: # 将信息发送给它们 send_message(client, message) |