redis 发布与订阅

频道的订阅与退订

数据结构
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 结构,结构中保存着被订阅的模式,以及订阅该模式的客户端。程序通过遍历链表来查找某个频道是否和某个模式匹配。
  • 当有新消息发送到频道时,除了订阅频道的客户端会收到消息之外,所有订阅了匹配频道的模式的客户端,也同样会收到消息。
  • 退订频道和退订模式分别是订阅频道和订阅模式的反操作。

你可能感兴趣的:(redis 发布与订阅)