频道的订阅与退订
数据结构
struct redisServer {
// ...
// 保存所有频道的订阅关系
dict *pubsub_channels;
// ...
};
示例:
image.png订阅:
def subscribe(*all_input_channels):
# 遍历输入的所有频道
for channel in all_input_channels:
# 如果 channel 不存在于 pubsub_channels 字典(没有任何订阅者)
# 那么在字典中添加 channel 键,并设置它的值为空链表
if channel not in server.pubsub_channels:
server.pubsub_channels[channel] = []
# 将订阅者添加到频道所对应的链表的末尾
server.pubsub_channels[channel].append(client)
退订:
def unsubscribe(*all_input_channels):
# 遍历要退订的所有频道
for channel in all_input_channels:
# 在订阅者链表中删除退订的客户端
server.pubsub_channels[channel].remove(client)
# 如果频道已经没有任何订阅者了(订阅者链表为空)
# 那么将频道从字典中删除
if len(server.pubsub_channels[channel]) == 0:
server.pubsub_channels.remove(channel)
模式的订阅与退订
数据结构:
struct redisServer {
// ...
// 保存所有模式订阅关系
list*pubsub_patterns;
// ...
};
pubsubPattern:
typedef struct pubsubPattern {
// 订阅模式的客户端
redisClient *client;
robj *pattern;
// ...
}pubsubPattern ;
示例:
image.png订阅:
image.png退订:
image.png发送消息:
发送消息到频道:
image.png发送消息到模式:
image.png查看订阅信息:
PUBSUB CHANNELS
PUBSUB CHANNELS [pattern]
- 无参数: 返回服务器当前被订阅的所有频道。
- 有参数: 返回那些与pattern模式相匹配的频道。
伪码:
image.png
PUBSUB NUMSUB
PUBSUB NUMSUB[channel-1 channel-2 ... channel-n]
返回频道的订阅者数量
伪码:
image.png
PUBSUB NUMPAT
返回服务器当前被订阅模式的梳理。
伪码:
image.png
重点
- 订阅信息由服务器进程维持的 redisServer.pubsub_channels 字典保存,字典的键为被订阅的频道,字典的值为订阅频道的所有客户端。
- 当有新消息发送到频道时,程序遍历频道(键)所对应的(值)所有客户端,然后将消息发送到所有订阅频道的客户端上。
- 订阅模式的信息由服务器进程维持的 redisServer.pubsub_patterns 链表保存,链表的每个节点都保存着一个 pubsubPattern 结构,结构中保存着被订阅的模式,以及订阅该模式的客户端。程序通过遍历链表来查找某个频道是否和某个模式匹配。
- 当有新消息发送到频道时,除了订阅频道的客户端会收到消息之外,所有订阅了匹配频道的模式的客户端,也同样会收到消息。
- 退订频道和退订模式分别是订阅频道和订阅模式的反操作。
网友评论