Redis的发布与订阅
Redis提供了发布订阅功能,可以用于消息的传输
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
Redis的发布订阅机制包括三个部分,publisher,subscriber和Channel
发布者和订阅者都是Redis客户端,Channel则为Redis服务器端。
发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。
频道/模式的订阅与退订
subscribe:订阅
命令:subscribe channel1 channel2 ..
Redis客户端1订阅频道1和频道2
127.0.0.1:6379> subscribe ch1 ch2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ch1"
3) (integer) 1
1) "subscribe"
2) "ch2"
3) (integer) 2
publish:发布消息
命令:publish channel message
Redis客户端2将消息发布在频道1和频道2上
127.0.0.1:6379> publish ch1 hello
(integer) 1
127.0.0.1:6379> publish ch2 world
(integer) 1
Redis客户端1接收到频道1和频道2的消息
1) "message"
2) "ch1"
3) "hello"
1) "message"
2) "ch2"
3) "world"
unsubscribe:
命令:unsubscribe channel [channel...]
psubscribe :模式匹配
每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等)。 news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类。
命令:psubscribe pattern [pattern...]
Redis客户端1订阅所有以ch开头的频道
127.0.0.1:6379> psubscribe ch*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "ch*"
3) (integer) 1
Redis客户端2发布信息在频道5上
127.0.0.1:6379> publish ch5 helloworld
(integer) 1
Redis客户端1收到频道5的信息
1) "pmessage"
2) "ch*"
3) "ch5"
4) "helloworld"
punsubscribe 退订模式
命令: punsubscribe [pattern [pattern ...]]
发布订阅的实现机制-数据结构
客户端(client)订阅某个频道或模式:
// 客户端 在server.h typedef struct client { ... //该client订阅的channels,以channel为key用dict的方式组织 dict *pubsub_channels; //该client订阅的pattern,以list的方式组织 list *pubsub_patterns; ... } client;
pubsub_patterns,表示该客户端订阅的所有模式
pubsub_channels,表明了该客户端订阅的所有频道
服务器端(RedisServer):
struct redisServer {
...//redis server进程中维护的channel dict,它以channel为key,订阅channel的client list为value
dict *pubsub_channels;//redis server进程中维护的pattern list
list *pubsub_patterns;
int notify_keyspace_events;
...
};
pubsub_channels,dict,key为channel,value是订阅该频道的客户端链表
当客户端 client7执行命令subscribe channel1 channel2 channel3 ,那么就会把这个客户端分别加到相应key的链表末尾。
-
当客户端向某个频道发送消息时,Redis首先在redisServer中的pubsub_channels中找出key为该频道的节点,遍历该节点的链表,即遍历订阅了该频道的所有客户端,将消息发送给这些客户端。
-
当使用
PUBLISH
发布消息到某个频道的时候,不仅订阅这个频道的所有客户端会收到消息,与这个模式匹配的客户端也会收到消息。 -
遍历结构体redisServer中的pubsub_patterns,找出匹配该频道模式的节点,将消息发送给该节点上所有订阅了该模式的客户端链表。
pubsub_patterns,链表,包含了该服务器端中的所有模式和订阅了这些模式的客户端
pubsub_patterns链表的每个节点都包含一个 redis.h/pubsubPattern 结构:
typedef struct pubsubPattern {
client *client; -- 订阅模式客户端
robj *pattern; -- 被订阅的模式
} pubsubPattern;
当有新的模式订阅者时,就将这个客户端分别加入到该模式的client中。
使用场景
哨兵模式
在Redis哨兵模式中,哨兵通过发布与订阅的方式与Redis主服务器和Redis从服务器进行通信。
Redisson框架使用
Redisson是一个分布式锁框架,在Redisson分布式锁释放的时候,是使用发布与订阅的方式通知的。