Redis 入门到入坑14------发布订阅
Redis发布/订阅模式
简介
Redis发布订阅(Pub/Sub)是一种消息传递模式,它允许发送消息的进程(发布者)向特定的接收消息的进程(订阅者)传递消息。在Redis中,发布者和订阅者都可以通过频道(channel)来发送和接收消息。
-
发布者:发布者向指定的频道发送消息。发布者可以发送各种类型的消息,例如字符串、哈希、列表等。
-
订阅者:订阅者订阅一个或多个频道,并接收这些频道中的消息。订阅者可以同时订阅多个频道,以接收不同类型的信息。
-
频道:频道是发布者和订阅者之间的通信媒介。发布者将消息发送到特定的频道,订阅者从这些频道接收消息。
-
持久化:Redis的发布订阅是持久化的,即使订阅者在消息发送时不在线,当订阅者再次连接时,它可以获取所有未接收的消息
下图展示了频道与订阅者的关系以及新消息发布时的流程
Redis 发布/订阅模式的工作流程
- 发布者向一个或多个频道发送消息。
- Redis将消息存储在内部缓冲区中,等待订阅者订阅相应的频道。
- 订阅者通过
SUBSCRIBE
命令订阅一个或多个频道。 - 当有消息发送到已订阅的频道时,Redis将消息发送给订阅者。
- 订阅者可以通过
UNSUBSCRIBE
命令取消订阅某个频道,不再接收该频道的消息
发布订阅模式的常用命令
- SUBSCRIBE channel [channel ...] :订阅指定的一个或者多个频道(推荐先执行订阅之后再发布,订阅成功之前发布的消息是接收不到的)
ruby
127.0.0.1:6379> subscribe c1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "c1"
3) (integer) 1
- PUBLISH channel message:将消息发送到指定的频道
sql
--- 发布消息的客户端
[root@gone ~]# redis-cli
127.0.0.1:6379> publish c1 hello_c1
(integer) 2
--- 之前订阅消息的客户端
127.0.0.1:6379> subscribe c1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "c1"
3) (integer) 1
1) "message" ------- 消息的种类
2) "c1" ------- 始发频道的名称
3) "hello_c1" ------- 实际的消息内容
- PSUBSCRIBE [pattern [pattern ...]]:订阅一个或多个符合给定模式的频道
arduino
-- 这个命令订阅了所有以 "redis1" 开头和以 "redis2" 开头的频道,并输出多条显示订阅成功的消息
PSUBSCRIBE redis1* redis2*
- PUBSUB [argument [argument ...]]]:查看订阅与发布系统状态。它由数个不同格式的子命令组成
sql
--- 返回活跃频道的列表
127.0.0.1:6379> pubsub channels
1) "c1"
2) "c2"
--- 返回c1频道的订阅者数量
127.0.0.1:6379> pubsub numsub c1
1) "c1"
2) (integer) 3
-- 只统计使用PSUBSCRIBE命令执行的,返回客户端订阅的唯---模式的数量
--- 客户端1下执行
127.0.0.1:6379> psubscribe a* b* c* d*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "a*"
3) (integer) 1
1) "psubscribe"
2) "b*"
3) (integer) 2
1) "psubscribe"
2) "c*"
3) (integer) 3
1) "psubscribe"
2) "d*"
3) (integer) 4
--- 客户端2下执行
127.0.0.1:6379> pubsub numpat
(integer) 4
- PUNSUBSCRIBE [pattern [pattern ...]]:退订所有给定模式的频道
arduino
--- 命令退订了所有以"redis1"开头和以"redis2"开头的频道,并输出多条显示退订成功的消息
PUNSUBSCRIBE redis1* redis2*
- UNSUBSCRIBE [channel ...]:取消订阅指定的频道
ruby
127.0.0.1:6379> unsubscribe c1
1) "unsubscribe"
2) "c1"
3) (integer) 0
案例演示
- 开启3个客户端,客户端A、B订阅消息,C发布消息
sql
--- 1.客户端A订阅:
127.0.0.1:6379> subscribe c1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "c1"
3) (integer) 1
--- 2.客户端B订阅
127.0.0.1:6379> subscribe c1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "c1"
3) (integer) 1
--- 3.客户端C发布
127.0.0.1:6379> publish c1 'hello channel c1'
(integer) 2
--- 4.查看客户端A
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "c1"
3) (integer) 1
1) "message"
2) "c1"
3) "hello channel c1"
--- 5.查看客户端B
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "c1"
3) (integer) 1
1) "message"
2) "c1"
3) "hello channel c1"
- 批量订阅和发布
sql
--- 批量订阅
--- 1.客户端A执行
127.0.0.1:6379> psubscribe a* b* c* d*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "a*"
3) (integer) 1
1) "psubscribe"
2) "b*"
3) (integer) 2
1) "psubscribe"
2) "c*"
3) (integer) 3
1) "psubscribe"
2) "d*"
3) (integer) 4
---2.客户端B执行
127.0.0.1:6379> pubsub numpat
(integer) 4
127.0.0.1:6379> publish c10 hello_channel_c10
(integer) 1
127.0.0.1:6379> publish a11 hello_channel_a11
(integer) 1
--- 3.查看客户端A的信息输出
127.0.0.1:6379> psubscribe a* b* c* d*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "a*"
3) (integer) 1
1) "psubscribe"
2) "b*"
3) (integer) 2
1) "psubscribe"
2) "c*"
3) (integer) 3
1) "psubscribe"
2) "d*"
3) (integer) 4
---- 输出的信息
1) "pmessage"
2) "c*"
3) "c10"
4) "hello_channel_c10"
1) "pmessage"
2) "a*"
3) "a11"
4) "hello_channel_a11"
发布订阅模式的缺点
Redis 的发布-订阅模式是一种非常强大的消息传递机制,它允许订阅者监听一个或多个频道,并在有消息发布到这些频道时接收它们。然而,这种模式也有一些潜在的缺点:
- 消息可靠性:在 Redis 的发布订阅模型中,消息是单向传输的。发布者将消息发布到一个通道(channel),然后所有订阅该通道的订阅者都会收到消息。然而,一旦消息被发布,Redis 不提供任何确保消息到达的机制。如果订阅者在消息发布时离线或者处理消息失败,那么消息可能会丢失。
- 消息传递的持久性:Redis 的发布订阅模型不保证消息的持久性。如果订阅者在消息发布后关闭或者崩溃,那么消息可能会丢失。为了解决这个问题,可以配置 Redis 持久化消息,但这样会增加额外的性能开销和存储需求。
- 消息的顺序性:在 Redis 的发布订阅模型中,多个订阅者可以同时接收到发布者发布的消息。然而,无法保证消息的顺序性。即,不同的订阅者可能会以不同的顺序接收到同样的一系列消息。如果需要严格的消息顺序性,可能需要额外的逻辑来处理。
- 消息的确认机制:在 Redis 的发布订阅模型中,没有内置的消息确认机制。当订阅者接收到消息后,它不会向发布者发送确认消息。这可能导致发布者无法确定消息是否成功传递给所有订阅者。为了解决这个问题,可以引入一个确认机制,但会增加系统的复杂性。
- 性能和资源利用:在大量并发订阅者和发布者的情况下,Redis 的发布订阅模型可能会对系统性能和资源利用产生影响。为了处理大量的订阅者和发布者,可能需要增加更多的 Redis 实例和网络带宽。此外,如果每个订阅者都接收所有发布的消息,可能会导致大量的网络流量和内存消耗。