Redis 发布/订阅介绍
  7jPfnBIFtnum 12天前 23 0

一、发布与订阅

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

redis通过PUBLISH和SUBSCRIBE等命令实现了订阅与发布模式,这个功能提供两种信息机制,分别是订阅/发布到频道、订阅/发布到模式的客户端。

 6.1 频道

 6.1.1 发布

Redis 发布/订阅介绍

发布者发布消息

发布者向频道channel:1发布消息hi

127.0.0.1:6379> publish channel:1 hi
(integer) 1

6.1.2 订阅

Redis 发布/订阅介绍

 

订阅者订阅消息

127.0.0.1:6379> subscribe channel:1
Reading messages... (press Ctrl-C to quit)
1) "subscribe" // 消息类型
2) "channel:1" // 频道
3) "hi" // 消息内容

执行subscribe后客户端会进入订阅状态,仅可以使subscribe、unsubscribe、psubscribe和punsubscribe这四个属于"发布/订阅"之外的命令

订阅频道后的客户端可能会收到三种消息类型

  • subscribe。表示订阅成功的反馈信息。第二个值是订阅成功的频道名称,第三个是当前客户端订阅的频道数量。
  • message。表示接收到的消息,第二个值表示产生消息的频道名称,第三个值是消息的内容。
  • unsubscribe。表示成功取消订阅某个频道。第二个值是对应的频道名称,第三个值是当前客户端订阅的频道数量,当此值为0时客户端会退出订阅状态,之后就可以执行其他非"发布/订阅"模式的命令了。

 6.1.3 数据结构

基于频道的发布订阅模式是通过字典数据类型实现的

struct redisServer {
    // ...
    dict *pubsub_channels;
    // ...
};

其中,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。

Redis 发布/订阅介绍

 

 6.1.3.1 订阅(channel)

当使用subscribe订阅时,在字典中找到频道key(如没有则创建),并将订阅的client关联在链表后面。

当client 10执行subscribe channel1 channel2 channel3时,会将client 10分别加到 channel1 channel2 channel3关联的链表尾部。

Redis 发布/订阅介绍

 6.1.3.2 发布

发布时,根据key,找到字典汇总key的地址,然后将msg发送到关联的链表每一台机器。

6.1.3.3 退订

遍历关联的链表,将指定的地址删除即可。

 

 6.2 模式(pattern)

pattern使用了通配符的方式来订阅

通配符中?表示1个占位符,*表示任意个占位符(包括0),?*表示1个以上占位符。

所以当使用 publish命令发送信息到某个频道时, 不仅所有订阅该频道的客户端会收到信息, 如果有某个/某些模式和这个频道匹配的话, 那么所有订阅这个/这些频道的客户端也同样会收到信息。

Redis 发布/订阅介绍

 6.2.1 发布

发布者发布消息

127.0.0.1:6379> publish b m1
(integer) 1
127.0.0.1:6379> publish b1 m1
(integer) 1
127.0.0.1:6379> publish b11 m1
(integer) 1

 6.2.2 订阅

订阅者订阅消息

127.0.0.1:6379> psubscribe b*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "b*"
3) (integer) 3
1) "pmessage"
2) "b*"
3) "b"
4) "m1"
1) "pmessage"
2) "b*"
3) "b1"
4) "m1"
1) "pmessage"
2) "b*"
3) "b11"
4) "m1"

 

 6.2.3 数据结构

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

struct redisServer {
    // ...
    list *pubsub_patterns;
    // ...
};
// 链表中的每一个节点结构如下,保存着客户端与模式信息
typedef struct pubsubPattern {
    redisClient *client;
    robj *pattern;
} pubsubPattern;

Redis 发布/订阅介绍

 

 6.2.3.1 发布

当发布者发布消息时,首先会发送到对应的频道上,在遍历模式列表,根据key匹配模式,匹配成功将消息发给对应的订阅者。

完成的发布伪代码如下:

def PUBLISH(channel, message):
    # 遍历所有订阅频道 channel 的客户端
    for client in server.pubsub_channels[channel]:
        # 将信息发送给它们
        send_message(client, message)
    # 取出所有模式,以及订阅模式的客户端
    for pattern, client in server.pubsub_patterns:
        # 如果 channel 和模式匹配
        if match(channel, pattern):
            # 那么也将信息发给订阅这个模式的客户端
            send_message(client, message)
 6.2.3.2 订阅

当有信的订阅时,会将订阅的客户端和模式信息添加到链表后面。

Redis 发布/订阅介绍

 

 6.2.3.3 退订

使用punsubscribe,可以将订阅者退订,将改客户端移除出链表。

 6.3 使用场景

 6.3.1 哨兵间通信

哨兵集群中,每个哨兵节点利用 Pub/Sub 发布订阅实现哨兵之间的相互发现彼此和找到 Slave。

哨兵与 Master 建立通信后,利用 master 提供发布/订阅机制在 `__sentinel__:hello`发布自己的信息,同时订阅这个频道来获取其他哨兵的信息,就这样实现哨兵间通信。

 6.3.2 消息队列

我们也可以利用 Redis 发布订阅实现 轻量级简单的 MQ 功能 ,实现上下游解耦,需要注意点是 Redis 发布订阅的消息不会被持久化,所以新订阅的客户端将收不到历史消息。

也不支持 ACK 机制,所以当前业务不能容忍这些缺点,那就使用专业的消息队列,如果能容忍那就能享受 Redis 快带来的优势。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 12天前 0

暂无评论

7jPfnBIFtnum