图解redis发布和订阅

目录

1.什么是发布订阅

1.1概念

1.2发布订阅过程

1.3发布订阅分为两类

2. 频道的订阅与退订

2.1subcribe

2.2退订频道

3. 模式的订阅和退订

3.1模式的订阅

3.2punsubscribe

4.频道和模式的发布

4.1频道的发布

4.2模式的发布


1.什么是发布订阅

1.1概念

1.发布订阅模式又叫观察者模式,是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
2.主要的目的是解耦消息发布者和消息订阅者之间的耦合,这点和设计模式中的观察者模式比较相似。
3.由三部分组成:发布者(pub),订阅者(sub)和频道(channel)
4.Redis 客户端可以订阅任意数量的频道。
5.Redis 在订阅者和发布者之间起到了消息路由的功能。

1.2发布订阅过程

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端

1.3发布订阅分为两类

 1.频道的发布订阅

 2.模式的发布订阅

2. 频道的订阅与退订

2.1subcribe

当一个客户端执行SUBSCRIBE命令订阅某个或某些频道的时候, 这个客户端与被订阅频道之间就建立起了一种订阅关系

格式  SUBSCRIBE channel [channel …]

底层原理 :

1.pubsub_channels字典 

Redis将所有频道的订阅关系都保存在服务器状态

struct redisServer {
// ...
//
保存所有频道的订阅关系
dict *pubsub_channels;
// ...
};

图形示意:

client-1、client-2、client-3三个客户端正在订阅"news.it"频道。

·客户端client-4正在订阅"news.sport"频道。

·client-5和client-6两个客户端正在订阅"news.business"频道。

 2.情况分类

1.如果频道已经有其他订阅者,那么它在pubsub_channels字典中必 然有相应的订阅者链表,程序唯一要做的就是将客户端添加到订阅者链 表的末尾。

2·如果频道还未有任何订阅者,那么它必然不存在于 pubsub_channels字典,程序首先要在pubsub_channels字典中为频道创建 一个键,并将这个键的值设置为空链表,然后再将客户端添加到链表, 成为链表的第一个元素

图形示意

SUBSCRIBE "news.sport" "news.movie”

1. ·更新后的pubsub_channels字典新增了"news.movie"键,该键对应的 链表值只包含一个client-10086节点,表示目前只有client-10086一个客户 端在订阅"news.movie"频道

2.至于原本就已经有客户端在订阅的"news.sport"频道,client-10086 的节点放在了频道对应链表的末尾

2.2退订频道

格式 unsub channel message

底层原理:

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

图形示意:

·程序会根据被退订频道的名字,在pubsub_channels字典中找到频 道对应的订阅者链表,然后从订阅者链表中删除退订客户端的信息。

·如果删除退订客户端之后,频道的订阅者链表变成了空链表,那 么说明这个频道已经没有任何订阅者了,程序将从pubsub_channels字典 中删除频道对应的键

执行之后 

UNSUBSCRIBE "news.sport" "news.movie"

 

3. 模式的订阅和退订

3.1模式的订阅

1.psubscribe命令

  • 格式: PSUBSCRIBE pattern [pattern …]

  • eg : PSUBSCRIBE China* 订阅以China为开头的所有频道

  • 底层原理

  • 1.redisServer.pubsub_patterns 属性是一个链表,链表中保存着所有和模式相关的信息:

    2.链表中的每个节点都包含一个 redis.h/pubsubPattern 结构:

    3.client 属性保存着订阅模式的客户端,而 pattern 属性则保存着被订阅的模式。

    4.每当调用 PSUBSCRIBE 命令订阅一个模式时,程序就创建一个包含客户端信息和被订阅模式的 pubsubPattern 结构,并将该结构添加到redisServer.pubsub_patterns 链表中

    举个例子,下图展示了一个包含两个模式的 pubsub_patterns 链表, 其中 client123 和 client256 都正在订阅 tweet.shop.* 模式

  • 如果这时客户端 client10086 执行 PSUBSCRIBE broadcast.list.* , 么 pubsub_patterns 链表将被更新成这样:

  •  

 note1

假设客户端同时订阅了某种模式和符合该模式的某个频道,那么发送给这个频道的消息将被客户端接收到两次,只不过这两条消息的类型不同,一个是message类型,一个是pmessage类型,但其内容相同

3.2punsubscribe

格式: PUNSUBSCRIBE [pattern [pattern …]]

原理:这个命令执行的是订阅模式的反操作:程序会删除redisServer.pubsub_patterns 链表中,所有和被退订模式相关联的 pubsubPattern 结构,这样客户端就不会再收到和模式相匹配的频道发来的信息。

note1 1.在SUBSCRIBE,PSUBSCRIBE,UNSUBSCRIBE和PUNSUBSCRIBE命令中,其返回值都包含了该客户端当前订阅的频道和模式的数量,当这个数量变为0时,该客户端会自动退出订阅状态。

2.PUBLISH和SUBSCRIBE的缺陷在于客户端必须一直在线才能接收到消息,断线可能会导致客户端丢失消息,除此之外,旧版的redis可能会由于订阅者消费不够快而变的不稳定导致崩溃,甚至被管理员杀掉

4.频道和模式的发布

4.1频道的发布

命令 PUSHLISH<channel><message>

因为服务器状态中的pubsub_channels字典记录了所有频道的订阅关 系,所以为了将消息发送给channel频道的所有订阅者,PUBLISH命令 要做的就是在pubsub_channels字典里找到频道channel的订阅者名单(一 个链表),然后将消息发送给名单上的所有客户端

例子1

PUBLISH "news.it" "hello"

那么PUBLISH命令将在pubsub_channels字典中查找键"news.it"对应 的链表值,并通过遍历链表将消息"hello"发送给"news.it"频道的三个订 阅者:client-1、client-2和client-3。

4.2模式的发布

发送信息到模式的工作也是由 PUBLISH 命令进行的。PUBLISH 除了将 message 发送到所有订阅 channel 的客户端之外,它还会将 channel 和 pubsub_patterns 中的模式进行对比,如果 channel 和某个模式匹配的话,那么也将 message 发送到订阅那个模式的客户端
 

eg.下图展示了一个带有频道和模式的例子, 其中 tweet.shop.* 模式匹配了tweet.shop.kindle 频道和 tweet.shop.ipad 频道, 并且有不同的客户端分别订阅它们三个

当有信息发送到 tweet.shop.kindle 频道时, 信息除了发送给 clientX 和 clientY 之外, 还会发送给订阅 tweet.shop.* 模式的 client123 和 client256 

 

本文链接:https://my.lmcjl.com/post/5297.html

展开阅读全文

4 评论

留下您的评论.