天天看点

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

文章目录

  • Redis发布订阅简介
  • 发布订阅的使用
    • 基于频道的发布/订阅
    • 基于模式的发布/订阅
  • 深入理解

Redis发布订阅简介

Redis中发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

Redis的

SUBSCRIBE

命令可以让客户端订阅任意数量的频道,每当有新信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端。

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

当有新消息通过

PUBLISH

命令发送给频道channel1时,这个消息就会被发送给订阅他的三个客户端:

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

发布订阅的使用

Redis有两种发布、订阅模式:
  1. 基于频道(channel)的发布/订阅
  2. 基于模式(pattern)的发布/订阅

基于频道的发布/订阅

发布者可以向指定的频道发送消息;订阅者可以订阅一个或者多个频道,所有订阅此频道的订阅者都会收到此消息。

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

发布者发布消息:

发布者发布消息的命令是

publish

,用法是

publish channel message

,消息发送出去之后,返回值表示接收这条消息的订阅者数量。发出去的消息不会被持久化,也就是有客户端订阅channel后,只能接收到后续发布到该频道的消息,之前的就接收不到了。

订阅者订阅频道:

订阅频道的命令是

subscribe

,可以同时订阅多个频道,用法是

subscribe channel1 [channel2 ...]

执行上面命令客户端会进入订阅状态,处于此状态下客户端不能使用除了

subscribe、unsubscribe、psubscribe、punsubscribe

这四个属于“发布/订阅”之外的命令,否则会报错。

进入订阅状态后客户端可能受到三种类型的回复,每种类型的回复都包含三个值,第一个值是消息的类型,根据类型的不同,第二个和第三个参数的含义可能不同。

消息类型:

  • subscribe

    :表示订阅成功的反馈信息。第二个值是订阅成功的频道名称,第三个是当前客户端订阅的频道数量。
  • message

    :表示接收到的消息,第二个值表示产生消息的频道名称,第三个值是消息的内容。
  • unsubscribe

    :表示成功取消订阅某个频道。第二个值是对应的频道名称,第三个值是当前客户端订阅的频道数量,当此值为0时客户端会退出订阅状态,之后就可以执行其他非“发布/订阅”模式的命令了。

基于模式的发布/订阅

如果有某个/某些模式和这个频道匹配的话,那么所有订阅这个/这些模式的客户端也同样会收到信息。

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

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

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

另一方面, 如果接收到信息的是频道 tweet.shop.ipad , 那么 client123 和 client256 同样会收到信息:

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

深入理解

基于频道的发布/订阅如何实现的?

底层是通过字典(图中的

pubsub_channels

)实现的,这个字典就用于保存订阅频道的信息:字典的键为正在被订阅的频道,而字典的值则是一个链表,链表中保存了所有订阅这个频道的客户端。

  • 数据结构:
Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解
  • 订阅:

当客户端调用

SUBSCRIBE

命令时,程序就将客户端和要订阅的频道在

pubsub_channels

字典中关联起来。

  • 发布:

当调用

PUBLISH channel message

命令,程序首先根据

channel

定位到字典的键,然后将信息发送给字典值链表中的所有客户端。

  • 退订:

使用

UNSUBSCRIBE

可以退订指定的频道,这个命令执行的是订阅的反操作:他从

pubsub_channels

字典的给定频道中,删除关于当前客户端的信息,这样被退订频道的信息就不会再发送给这个客户端。

基于模式的发布/订阅如何实现的?

底层是

pubsubPattern

节点的链表。

  • 数据结构:

redisServer.pubsub_patterns

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

struct redisServer {
    // ...
    list *pubsub_patterns;
    // ...
};
           

链表中的每个节点都包含一个

redis.h/pubsubPattern

结构:

typedef struct pubsubPattern {
    redisClient *client;
    robj *pattern;
} pubsubPattern;
           

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

每当调用

PSUBSCRIBE

命令订阅一个模式时,程序就创建一个包含客户端信息和被订阅模式的

pubsubPattern

结构,并将该结构添加到

redisServer.pubsub_patterns

链表中。

Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解

上图为一个包含两个模式的 pubsub_patterns 链表, 其中 client123 和 client256 都正在订阅 tweet.shop.* 模式。

  • 订阅:

    如果这时客户端 client10086 执行

    PSUBSCRIBE broadcast.list.*

    , 那么 pubsub_patterns 链表将被更新成这样:
    Redis(四)--发布订阅模式详解Redis发布订阅简介发布订阅的使用深入理解
    通过遍历整个 pubsub_patterns 链表,程序可以检查所有正在被订阅的模式,以及订阅这些模式的客户端。
  • 发布:

    发送信息到模式的工作也是由

    PUBLISH

    命令进行的, 显然就是匹配模式获得

    Channels

    ,然后再把消息发给客户端。
  • 退订:

    使用

    PUNSUBSCRIBE

    命令可以退订指定的模式, 这个命令执行的是订阅模式的反操作: 程序会删除

    redisServer.pubsub_patterns

    链表中, 所有和被退订模式相关联的 pubsubPattern 结构, 这样客户端就不会再收到和模式相匹配的频道发来的信息。

感谢并参考:

https://redisbook.readthedocs.io/en/latest/feature/pubsub.html

https://www.cnblogs.com/qlqwjy/p/9763754.html

https://blog.csdn.net/ibigboy/article/details/95751542