欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

redis设计与实现读书笔记——发布与订阅

程序员文章站 2022-05-21 13:44:24
...

频道的订阅与退订

Redis将所有频道的订阅关系都保存在服务器状态的pubsub_channels字典里面,这个字典的键是某个被订阅的频道,而键的值则是一个链表,链表里面记录了所有订阅这个频道的客户端。

struct redisServer{
    //……

    //保存所有频道的订阅关系
    dict *pubsub_channels;

    //……
};

redis设计与实现读书笔记——发布与订阅

  • 订阅频道

每当客户端执行SUBSCRIBE命令订阅某个或某些频道的时候,服务器都会将客户端与被订阅频道在pubsub_channels字典中进行关联。

def subscribe(*all_input_channels)

    #遍历输入的所有频道
    for channel in all_input_channels;

        #如果channel不存在于pubsub_channels字典,则在字典中添加该键,并设置它的值为空链表
        if channel not in server.pubsub_channels:
            server.pubsub_channels[channel]=[]

        #将订阅者添加到频道所对应的链表的末尾
        server.pubsub_channels[channel].append(client)
  • 退订频道

UNSUBSCRIBE命令的行为和SUBSCRIBE命令的行为正好相反,当一个客户端退订某个或某些频道的时候,服务器将从pubsub_channels中解除客户端与被退订频道之间的关联。

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)

       

模式的订阅与退订

Redis将所有模式的订阅关系都保存在服务器状态的pubsub_patterns属性里面

struct redisServer{
    //……

    //保存所有模式的订阅关系
    list *pubsub_patterns;

    //……
};

redis设计与实现读书笔记——发布与订阅

  • 订阅模式
def psubscribe(*all_input_patterns)

    #遍历输入的所有模式
    for pattern in all_input_patterns;

        #创建新的pubsubPattern结构,记录被订阅的模式,以及订阅模式的客户端
        pubsubPattern = create_new_pubsubPattern()
        pubsubPattern.client = client
        pubsubPattern.pattern = pattern

        #将新的pubsubPattern追加到pubsub_patterns链表末尾
        server.pubsub_patterns.append(pubsubPattern)
  • 退订模式
def punsubscribe(*all_input_patterns)

    #遍历所有要退订的模式
    for pattern in all_input_patterns;

        #遍历subpub_patterns链表中的所有pubsubPattern结构
        for pubsubPattern in server.pubsub_patterns:

        #如果当前客户端与subpubPattern记录的客户端相同
        #并且退订的模式也和pubsubPattern记录的模式相同
        if client == pubsubPattern.clent and pattern = pubsubPattern.pattern

            #将这个pubsubPattern删除
            server.pubsub_patterns.remove(pubsubPattern)

发送消息

当一个Redis客户端执行PUBLISH <channel> <message>命令将消息message发送给频道channel的时候,服务器需要执行以下两个动作:

  1. 将消息message发给channel频道的所有订阅者
  2. 如果有一个或者多个模式pattern与频道channel相匹配,那么将消息message发送给pattern模式的订阅者
def channel_publish(channel,message)

    #如果模式不存在于pubsub_channels字典中,直接返回
    if channel not in server.pubsub_channels
        return

    #遍历channel频道的订阅者链表,将消息发送给链表中的每一个订阅者
    for subscriber in server.pubsub_channels[channel]
        send_message(subscriber,message)

===========================================================================

def pattern_publish(channel,message)

    #遍历所有模式订阅消息
    for pubsubpattern in server.pubsub_patterns

        #如果频道和模式相匹配
        if match(channel,pubsubPattern.pattern):

            #那么将消息发送给该模式的客户端
            send_message(pubsubPattern.client,message)

============================================================================

def publish(channel,message)

    channel_publish(channel,message)
    pattern_publish(channel,message)

查看订阅消息

  • PUBSUB CHANNELS

PUBSUB CHANNELS [pattern] 子命令用于返回服务器当前被订阅的频道,其中pattern参数是可选的:如果不给定pattern参数,那么命令返回服务器当前被订阅的所有频道;如果给定pattern参数,那么命令返回服务器当前被订阅的频道中与pattern模式相匹配的频道。

  • PUBSUB NUMSUB

PUBSUB NUMSUB [channel-1 channel-2 …… channel-n]子命令接受任意多个频道作为输入参数,并返回这些频道的订阅者数量。

  • PUBSUB NUMPAT

PUBSUB NUMPAT子命令用于返回服务器当前被订阅模式的数量。