简介
Redis 支持简易的 publish/subscribe (发布/订阅)模式,简称 PubSub。
在 publish/subscribe 模式中,主要有三个部分组成:
- publisher(发布者):发送消息到频道中,每次只能往一个频道发送一条消息。
- subscriber(订阅者):订阅频道,订阅者可同时订阅多个频道。订阅频道后,订阅者线程处于阻塞状态,一直等待接收消息。
- channel(频道):发布者向订阅者发送消息的通道。
发布者一旦向某个频道发送消息,订阅了该频道的多个订阅者,都能立马收到消息。但订阅者无法获取在它订阅之前,就已经产生的消息。
基本命令
publish 用于发布消息到指定的通道(频道),返回该通道当前在线的订阅数
语法:publish channel message
# 发布消息到 ch1
127.0.0.1:6379> publish ch1 c1_test1
(integer) 2
# 发布消息到 ch2
127.0.0.1:6379> publish ch2 c2_test2
(integer) 1
subscribe 用于订阅一个或多个指定的通道
语法:subscribe channel [channel ...]
# 订阅通道 ch1
127.0.0.1:6379> subscribe ch1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ch1"
3) (integer) 1
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
psubscribe 用于订阅一个或多个符合指定模式的通道
语法:psubscribe pattern [pattern ...]
# 订阅以 ch 开头的通道
127.0.0.1:6379> psubscribe ch*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "ch*"
3) (integer) 1
unsubscribe 用于退订一个或多个指定的通道
语法:unsubscribe [channel [channel ...]]
punsubscribe 用于退订一个或多个符合指定模式的通道
语法:punsubscribe [pattern [pattern ...]]
pubsub 查看发布/订阅的系统状态
语法:pubsub subcommand [argument [argument ...]]
# 返回当前活跃的通道,即有客户端在线订阅的通道
127.0.0.1:6379> pubsub channels
1) "ch2"
2) "ch1"
# 返回 ch1、ch2 当前在线的订阅数
127.0.0.1:6379> pubsub numsub ch1 ch2
1) "ch1"
2) (integer) 2
3) "ch2"
4) (integer) 1
应用场景
利用 Redis 的 publish/subscribe 模式来做日志收集和处理。
需要注意的是,publish/subscribe 模式中的消息不是持久化的,这些消息也不会保存到 Redis 的 db 库。而且,如果某一个订阅者中途掉线,掉线期间的消息对于它来说就丢失了。
如果对消息的完整性有较高的要求,推荐使用更为专业的消息队列中间件,比如 kafka、rabbitmq 等。
与 list 实现的消息队列的对比
我们知道,Redis 基于 list 可实现简易的消息队列,比如采用 lpush + brpop 命令的方式。
- 多消费者组:当多个客户端同时消费同一个 list 消息队列时,消费者 A1 使用 brpop 消费了消息,消费者 A2 就无法获取该消息。而在发布订阅模式中,多个订阅者可以订阅相同的频道,频道内的消息会分发(广播)给每一个消费者。
- 断点消费:对于 list 消息队列,消费者断开后重连,仍然可以从 list 中的断点消费还没消费的数据。而在发布订阅模式中,如果订阅者断开重连,就会丢失断开期间发布者发布的消息。
与 Kafka 的对比
- 持久化:Kafka 会将数据持久化到磁盘,而 Redis 的发布订阅做不到。
- 断点消费:Kafka 会记录每个消费者消费的主题(topic)的偏移量(offset),使得消费者可以从断开的偏移量继续消费。而 Redis 的发布订阅做不到断点消费。
- 多消费者组:在 Kafka 中,不同的消费者组中的消费者消费相同的主题时会各自维护一个偏移量,因此不会出现 A 消费之后的数据 B 就消费不到的情况。在 Redis 的发布订阅模式中,多个订阅者也可订阅相同的频道,频道内的消息会分发(广播)给每一个消费者。
- 消费方式:在 Redis 的发布订阅模式中,数据消费情况是由发布者控制的,当发布者把消息发布到频道中后,该频道的在线消费者就会立马消费消息。而在 Kafka 中消费进度是由消费者控制的,消费者从 topic 主题 拉取数据并记录偏移量。