Redis原理之订阅与发布
简介
Redis 通过 PUBLISH 、SUBSCRIBE 等命令实现了订阅与发布模式,这个功能提供两种信息 机制,分别是订阅/发布到频道和订阅/发布到模式,下文先讨论订阅/发布到频道的实现,再讨 论订阅/发布到模式的实现。
频道的订阅与信息发送
Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道,每当有新信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端。
下图clientA clientB clientC 都订阅了频道channel1。
当有新消息通过 PUBLISH 命令发送给频道 channel1 时,这个消息就会被发送给订阅它的三个客户端:
订阅频道
每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构,结构的pubsub_channels 属性是一个字典,这个字典就用于保存订阅频道的信息:
struct redisServer { // ...
dict *pubsub_channels;
// ...
};
其中,字典的键为正在被订阅的频道,而字典的值则是一个链表,链表中保存了所有订阅这个 频道的客户端。
下图clientA clientB clientC 都订阅了频道channel1。其他频道也被其他客户端订阅。
当客户端clientX 执行命令 SUBSCRIBE channel1 channel2。
127.0.0.1:6379> subscribe channel1 channel2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "subscribe"
2) "channel2"
3) (integer) 2
pubsub_channels 将变成下面这个样子
发送信息到频道
了解了 pubsub_channels 字典的结构之后,解释 PUBLISH 命令的实现就非常简单了:当调 用 PUBLISH channel message 命令,程序首先根据 channel 定位到字典的键,然后将信息发 送给字典值链表中的所有客户端。
下面演示了clientA 和 clientB 订阅 channel1 。client-p 发布信息 的操作。
- clientA 订阅 channel1
127.0.0.1:6379> subscribe channel1 channel2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "subscribe"
2) "channel2"
3) (integer) 2
- clientB 订阅 channel1
127.0.0.1:6379> subscribe channel1 channel2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "subscribe"
2) "channel2"
3) (integer) 2
- client-p 发布信息
127.0.0.1:6379> publish channel1 "Hello World"
(integer) 2
127.0.0.1:6379>
- clientA 和 client B 信息如下:
clientA
1) "message"
2) "channel1"
3) "Hello World"
clientB
1) "message"
2) "channel1"
3) "Hello World"
退订频道
使用 UNSUBSCRIBE 命令可以退订指定的频道,这个命令执行的是订阅的反操作:它从 pubsub_channels 字典的给定频道(键)中,删除关于当前客户端的信息,这样被退订频道的 信息就不会再发送给这个客户端。
127.0.0.1:6379> unsubscribe channel1
1) "unsubscribe"
2) "channel1"
3) (integer) 0
127.0.0.1:6379>