Redis发布与订阅操作
程序员文章站
2022-05-21 21:26:08
...
文章目录
引言
Redis支持频道订阅和模式订阅;
-
频道订阅:订阅的频道和发布消息的频道相同时,客户端可以接收到消息,如一个客户端订阅频道
news.it
,则只有频道news.it
的消息才可以发送给该客户端; -
模式订阅:一个模式可以匹配一个或多个频道,当发布消息的频道与订阅的频道模式匹配时,客户端可以接收到消息,如一个客户端订阅模式
news.[ie]t
,则它可以接收发布到频道news.it
和news.et
的消息;
1. 数据结构
1.1 频道字典
- 用于频道订阅;
- 多个客户端可以订阅相同的频道,在服务器的
redisServer
结构里有一个pubsub_channels
属性,是一个字典,维护了所有被订阅的频道; - 字典的键是被订阅的频道,字典的值则是一个链表,链表里记录了所有订阅这个频道的客户端;
struct redisServer{
// ...
// 保存所有频道的订阅关系
dict *pubsub_channels;
// ...
};
2. 模式链表
- 用于模式订阅;
- 一个模式可以匹配一个或多个频道;每个客户端订阅的模式可能各不相同,所以将客户端和订阅的模式构建成一个
pubsubPattern
结构,然后将多个订阅构成一张链表,存放在redisServer
的pubsub_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设计与实现》黄建宏 著,机械工业出版社.
上一篇: redis-发布与订阅
下一篇: WebSocket,实现简单的广播功能