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

频道的订阅与退订

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

struct redisServer{
    //……

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

    //……
};

redis设计与实现读书笔记——发布与订阅_第1张图片

  • 订阅频道

每当客户端执行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设计与实现读书笔记——发布与订阅_第2张图片

  • 订阅模式
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 命令将消息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子命令用于返回服务器当前被订阅模式的数量。

 

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