Redis(设计与实现):---发布与订阅之模式的订阅与退订(PSUBSCRIBE命令、PUNSUBSCRIBE命令、pubsub_patterns属性、struct pubsubPattern)

Redis的发布订阅功能允许客户端通过PSUBSCRIBE命令订阅模式,如'news.*',并将消息广播给匹配模式的订阅者。当使用PUNSUBSCRIBE时,客户端可以退订已订阅的模式。pubsub_patterns属性存储所有模式订阅关系,结构包含模式和订阅客户端信息。文章通过实例解析了PSUBSCRIBE和PUNSUBSCRIBE的执行过程。
摘要由CSDN通过智能技术生成

pubsub_patterns属性

  • 上一篇文章说过,服务器将所有频道的订阅关系都保存在服务器状态的pubsub_channels属性里
    面,与此类似,服务器也将所有模式的订阅关系都保存在服务器状态的pubsub_patterns属性里面:
struct redisServer {
    // ...
    //保存所有模式订阅关系
    list *pubsub_patterns;
    // ...
};
  • pubsub_patterns属性是一个链表,链表中的每个节点都包含着一个pubsubPattern结构
    这个结构的pattern属性记录了被订阅的模式,而client属性则记录了订阅模式的客户端:
typedef struct pubsubPattern {
    //订阅模式的客户端
    redisClient *client;
 
    //被订阅的模式
    robj *pattern;
} pubsubPattern;

下图是一个pubsubPattern结构示例,它显示客户端client-9正在订阅模式"news.

在这里插入图片描述
下图展示了一个pubsub_patterns链表示例,这个链表记录了以下信息:

  • 客户端client-7正在订阅模式"music.*"
  • 客户端client-8正在订阅模式"book.*"
  • 客户端client-9正在订阅模式"news.*"
    在这里插入图片描述

一、何为模式的订阅

客户端还可以通过执行PSUBSCRIBE命令订阅一个或多个模式,从 而成为这些模式的订阅者:每当有其他客户端向某个频道发送消息时,消息不仅会被发送给 这个频道的所有订阅者,它还会被发送给所有与这个频道相匹配的模式的订阅者

演示案例

举个例子,假设如下图所示:

  • 客户端A正在订阅频道"news.it"。
  • 客户端B正在订阅频道"news.et"
  • 客户端C和客户端D正在订阅与"news.it"频道和"news.et"频道相匹配的模式"news.[ie]t"
    在这里插入图片描述
    如果这时某个客户端执行PUBLISH命令,向"news.it"频道发送消息"hello",那么不仅正在订阅"news.it"频道的客户端A会收到消 息,客户端C和客户端D也同样会收到消息,因为这两个客户端正在订阅匹配"news.it"频道 的"news.[ie]t"模式,如下图所示:
PUBLISH "news.it" "hello"

在这里插入图片描述
与此类似,如果某个客户端执行下面的命令,向"news.et"频道发送消息"world",那么不仅正在订阅"news.et"频道的客户端B会收到消 息,客户端C和客户端D也同样会收到消息,因为这两个客户端正在订阅匹配"news.et"频道 的"news.[ie]t"模式,如下图所示:

PUBLISH "news.et" "world"

在这里插入图片描述

二、模式的订阅(PSUBSCRIBE命令)

每当客户端执行PSUBSCRIBE命令订阅某个或某些模式的时候,服务器会对每个被订阅的模式执行以下两个操作:

  • 新建一个pubsubPattern结构,将结构的pattern属性设置为被订阅的模式,client属性设置为订阅模式的客户端
  • 将pubsubPattern结构添加到pubsub_patterns链表的表尾

演示案例
举个例子,假设服务器中 pubsub_patterns链表的当前状态如下图所示:

在这里插入图片描述

  • 那么当客户端client-9执行下面的命令之后,pubsub_patterns链表将更至新如下图所示的状态,其中用虚线包围的是新添加的
    pubsubPattern结构:
PSUBSCRIBE "news.*"

在这里插入图片描述

  • PSUBSCRIBE命令的实现原理可以用以下伪代码来描述:
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)

三、模式的退订

模式的退订命令PUNSUBSCRIBE是PSUBSCRIBE命令的反操作:当一个客户端退订某个或某些模式的时候,服务器将在pubsub_patterns链表中查找并删除那些pattern属性为被退订模式,并且client属性为执行退订命令的客户端的pubsubPattern结构

演示案例
举个例子,假设服务器pubsub_patterns链表的当前状态如下图所示:

在这里插入图片描述
那么当客户端client-9执行下面的命令,client属性为client-9,pattern属性为"news.*"的pubsubPattern结构将被删除, pubsub_patterns链表将更新至下图所示的样子:

在这里插入图片描述

  • PUNSUBSCRIBE命令的实现原理可以用以下伪代码来描述:
def punsubscribe(*all_input_patterns):
        # 遍历所有要退订的模式
        for pattern in all_input_patterns:
            # 遍历pubsub_patterns 链表中的所有pubsubPattern 结构
            for pubsubPattern in server.pubsub_patterns:
                #如果当前客户端和pubsubPattern 记录的客户端相同
                # 并且要退订的模式也和pubsubPattern 记录的模式相同
                if client == pubsubPattern.client and \
                        pattern == pubsubPattern.pattern:
                    # 那么将这个pubsubPattern 从链表中删除
                    server.pubsub_patterns.remove(pubsubPattern)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值