

Redis发布订阅原理与实践
source link: https://blog.51cto.com/molu2013/5044365
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Redis发布订阅原理与实践
原创Redis提供了发布订阅功能,可以用于消息的传输, 通过 PUBLISH 、 SUBSCRIBE 和 PSUBSCRIBE 等命令实现发布和订阅功能
频道的发布订阅
基于Channel的消息事件,这一类消息和Redis中存储的Keys没有太多关联,这类消息事件是独立使用(PUBLISH,SUBSCRIBE)
Redis将所有频道的订阅关系都保存在服务器状态的 pubsub_channels 字典,字典的键是某个被订阅的频道,而对应值则是一个链表,链表里记录了所有订阅这个频道的客户端。
//...
// 保存所有频道订阅关系
dict *pubsub_channels; /* Map channels to list of subscribed clients */
//...
}
一个pubsub_channels字典示例如下:
client-1、client-2三个客户端正在订阅 “redis” 频道
客户端 client-3 正在订阅 “mysql” 频道
频道有订阅者
在pubsub_channels字典中已存在该频道,此时server端会将订阅者客户端添加到该频道的链表末端
频道无订阅者
pubsub_channels字典中无此频道,在字典中创建频道,并此客户端放至该频道链表的第一位
1、订阅普通频道或多频道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redis"
3) (integer) 1
1) "subscribe"
2) "mysql"
3) (integer) 2
1) "message"
2) "redis"
3) "1"
1) "message"
2) "mysql"
3) "1"
模式的发布订阅
消息事件主要是对Redis中存储的Keys信息的变化事件进行通知,可以用来向订阅者通知Redis中符合订阅条件的Keys的各种事件(需要redist开启notify-keyspace-events参数,PSUBSCRIBE订阅),还可以通过Channel订阅消息,模式订阅psubscribe的Channel订阅和subscribe命令类似。
Redis将所有模式的订阅关系都保存在服务器状态的 pubsub_patterns 链表,链表的每个节点都包含着一个 pubsub Pattern 结构,这个结构的 pattern 属性记录了被订阅的模式,而 client 属性则记录了订阅模式的客户端。
//...
// 保存所有模式订阅关系
list *pubsub_patterns; /* A list of pubsub_patterns */
dict *pubsub_patterns_dict; /* A dict of pubsub_patterns */
int notify_keyspace_events; /* Events to propagate via Pub/Sub. This is an
xor of NOTIFY_... flags. */
//...
}
一个pubsub_patterns链表示例:
客户端 client-7 正在订阅模式 "redis*"
客户端 client-8 正在订阅模式 "mysql*"
当客户端执行PSUBSCRIBE。redis server端会做如下操作
1、新建一个 pubsubPattern结果,将结构的 pattern 属性设置为被订阅的模式,client 属性设置为订阅模式的客户端;
2、将pubsubPattern结构添加到 pubsub_patterns 链表的尾部
- 订阅模糊频道
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "redis*"
3) (integer) 1
1) "psubscribe"
2) "mysql*"
3) (integer) 2
1) "pmessage"
2) "mysql*"
3) "mysql2"
4) "1"
1) "pmessage"
2) "redis*"
3) "redis2"
4) "1"
- 订阅Redis key事件
需redis server端开启notify-keyspace-events参数,参数含义如下:
E:启用keyevent键事件通知,客户端可以使用__keyevent@<db>__为前缀的格式使用订阅功能。
g:监控一般性事件,包括但不限于对del,expire,rename事件的监控。
$:启用对字符串格式(即一般K-V结构)命令的监控。
l:启用对List数据结构命令的监控。
s:启用对Set数据结构命令的监控。
h:启用对Hash数据结构命令的监控。
z:启用对ZSet数据结构命令的监控。
x:启用对过期事件的监控。
e:启用对驱逐事件的监控,当某个键因maxmemory达到设置时,使用策略进行内存清理,会产生这个事件。
A:g$lshzxe通配符组合的别名,也就是说”AKE”这样的通配符组合,意味着所有事件。
notify-keyspace-events "AKE"
// 只监控字符串结构的所有事件,包括键空间通知和键事件通知
notify-keyspace-events "g$KExe"
// 只监控所有键事件通知
notify-keyspace-events "AE"
// 只监控Hash数据解构的键空间通知
notify-keyspace-events "ghKxe"
// 只监控Set数据结构的键事件通知
notify-keyspace-events "gsExe"
(1)订阅0号数据库中,所有的键变化事件,进行键空间通知
(1)订阅0号数据库中,所有的键变化事件,进行键事件通知
(2) 订阅0号数据库,test_redis_模糊键变化事件,进行键空间通知和键事件通知
(3)订阅0号数据库中,模糊的键变化事件,进行键空间通知
- 查看所有的频道:PUBSUB CHANNELS
- 查询订阅者的数量:PUBSUB NUMSUB
- 查询服务器被订阅者的数量:PUBSUB NUMPAT
- Redis无法对消息持久化存储,一旦消息被发送,如果没有订阅者接收,那么消息就会丢失
- Redis没有提供消息传输保障,当客户端连接超时等情况发生时,消息不会被重新发送给客户端
- 订阅过期key时,只有当key被真正清理才会被发送道订阅通道,ttl 为0 不会被发送(这种情况一般发生在大批量的key过期集中在一个时间,redis负载相对较高高)
- 消息位广播模式,订阅的客户端都会收到相同的消息,客户端会有重复消费问题
- 赞
- 收藏
- 评论
- 分享
- 举报
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK