Redis发布与订阅操作

引言

Redis支持频道订阅和模式订阅;

  • 频道订阅:订阅的频道和发布消息的频道相同时,客户端可以接收到消息,如一个客户端订阅频道news.it,则只有频道news.it的消息才可以发送给该客户端;
  • 模式订阅:一个模式可以匹配一个或多个频道,当发布消息的频道与订阅的频道模式匹配时,客户端可以接收到消息,如一个客户端订阅模式news.[ie]t,则它可以接收发布到频道news.itnews.et的消息;

1. 数据结构

1.1 频道字典

  • 用于频道订阅;
  • 多个客户端可以订阅相同的频道,在服务器的redisServer结构里有一个pubsub_channels属性,是一个字典,维护了所有被订阅的频道;
  • 字典的键是被订阅的频道,字典的值则是一个链表,链表里记录了所有订阅这个频道的客户端;
struct redisServer{
    // ...
    
    // 保存所有频道的订阅关系
    dict *pubsub_channels;
    
    // ...
};

在这里插入图片描述

2. 模式链表

  • 用于模式订阅;
  • 一个模式可以匹配一个或多个频道;每个客户端订阅的模式可能各不相同,所以将客户端和订阅的模式构建成一个pubsubPattern结构,然后将多个订阅构成一张链表,存放在redisServerpubsub_patterns属性里;
struct redisServer{
    // ...
    
    // 保存所有模式订阅关系
    list *pubsub_patterns;
    
    // ...
};

typedef struct pubsub_pattern{
    // 订阅模式的客户端
    redisClient *client;
    
    // 被订阅的模式
    robj *pattern;
}pubsub_pattern;

在这里插入图片描述

2. 发布订阅命令

2.1 订阅频道命令 subscribe

# 订阅频道 "news.sport" 和 "news.movie"
SUBSCRIBE "news.sport" "news.movie"

每当客户端执行SUBSCRIBE命令订阅某个或某些频道时,服务器都会将客户端与被订阅的频道在pubsub_channels字典中进行关联:

  • 如果频道已经有其他订阅者(字典中已经存在键为当前频道的订阅者链表),那么服务端直接将客户端添加到订阅者链表的末尾;
  • 如果频道还未有任何订阅者(字典中没有存在键为当前频道的订阅者链表),服务器首先在pubsub_channels字典中为频道创建一个键,并将这个键的值设置为空链表,然后再将客户端添加到链表,成为链表的第一个元素;

2.2 退订频道 unscubscribe

# 退订频道 "news.sport" 和 "news.movie"
UNSUBSCRIBE "news.sport" "news.movie"

当一个客户端退订某个频道或者某些频道时,服务器将从pubsub_channels字典中解除客户端与频道之间的关联:

  • 程序会根据根据退订的频道名字,在pubsub_channels字典中找到频道对应的订阅者链表,然后从订阅者链表中删除退订客户端的信息;
  • 如果删除退订客户端之后,频道的订阅者链表变成了空链表,那么说明这个频道已经没有任何订阅者了,程序将从pubsub_channels字典中删除频道对应的键;

2.3 订阅模式 psubscribe

# 订阅所有以 "news."开头的频道
PSUBSCRIBE "news.*"

订阅模式是服务器端的pubsub_patterns链表中添加节点;

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

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

2.4 退订模式 punsubscribe

# 退订模式 "news.*"
PUNSUBSCRIBE "news.*"

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

2.5 发送消息 publish

PUBLISH <channel> <message>

# 向频道 "news.it"发送 "hello"消息
PUBLISH "news.it" "hello"

当一个客户端执行PUBLISH命令将消息message发送给频道channel时,服务器需要执行以下两个操作:

  • 查询pubsub_channels字典,将消息发送给channel频道的所有订阅者;
  • 遍历pubsub_patterns链表,如果某个订阅模式pattern与频道channel相匹配,那么将消息发送给pattern模式的订阅者;

注意:

  • 发送消息只有一个命令PUBLISH
  • PUBLISH可以同时将消息发送给频道订阅者模式订阅者

参考文献

  • 《Redis设计与实现》黄建宏 著,机械工业出版社.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值