Redis 的订阅发布功能是什么?你了解吗?

Sherwin.Wei Lv7

Redis 的订阅发布功能是什么?你了解吗?

回答重点

Redis 的订阅发布功能(Publish/Subscribe,简称 Pub/Sub),是一种消息通信机制,用于在不同客户端之间实现消息的实时传递和广播。使用 Pub/Sub 模型,客户端可以订阅一个或多个频道,当有其他客户端向这些频道发布消息时,所有订阅了该频道的客户端都会立即收到消息。

主要功能包括:

  • 发布(Publish):某个客户端向指定的频道发布消息。
  • 订阅(Subscribe):一个或多个客户端订阅指定的频道,并在频道接收到消息时立刻获取该消息。

扩展知识

什么是发布/订阅模型?

发布/订阅其实属于消息队列中的一种消息通信模型,生产者(pub)发送消息,订阅者(sub)接收消息。

这里我们展示一下 Redis 的发布/订阅逻辑。如下图所示,发布者向一个或者多个频道发布消息,订阅者可以订阅一个或者多个频道所发布的消息。

当发布者发送新消息到对应的频道的时候,订阅者可以收到对应的信息。

Snipaste_2024-05-16_22-22-00.jpg

Redis 实现发布/订阅

简单演示下 Redis 发布/订阅模型的使用。

首先我们先创建并发布一个 message 到 Redis 频道,这里我们用三条信息进行对应的测试,如图所示

1
publish channel message
Snipaste_2024-05-16_22-30-25.jpg

然后实现对应的频道订阅

1
subscribe channel 
Snipaste_2024-05-16_22-32-55.jpg

可以看到,频道发布的消息都被消费到了。

解析下上述结果。

首先是 subscribe 以及 channel,其分别表示执行订阅以及订阅的频道。

integer 1 表示订阅成功。

message 表示接收到的消息,之后出现的 channel 表示订阅频道,后面就是消息数据。

订阅成功之后,客户端会一直保持订阅状态,直到手动取消订阅或连接断开。

到此为止,一个基于 Redis 简单的发布/订阅模型就成功实现了。

它支持消费者阻塞式拉取消息,另外还提供了匹配订阅,消费者可以根据一定的规则,订阅多个队列。

例如subscribe mianshiya.*,此时如果生产者发布了 mianshiya.1mianshiya.2mianshiya.3 等队列的消息,消费者都可以接收到。

命令汇总

  • SUBSCRIBE channel:用于订阅某个频道。
  • PUBLISH channel message:用于向某个频道发布消息。
  • UNSUBSCRIBE channel:取消订阅某个频道。
  • PSUBSCRIBE pattern:支持使用模式匹配订阅(如通配符*)来动态地订阅多个频道。

Redis 发布/订阅模型的原理

Redis 是如何实现这个功能的呢?实际上很简单。

消费者订阅队列,实际上就是在 Redis 中保存了一个映射关系,即队列 x -> 消费者 1。

如果生产者往这个队列 x 发送一条消息,Redis 不会做任何的存储动作,而是查找映射关系,然后立马转发给消费者1,所以 Redis 实际上就是提供了一个“转发通道”。如果找到多个映射关系,那么就都转发,所以支持多消费者的实现。

因此,不论是 rdb 还是 aof 都不会存储消息

Redis 发布/订阅模型的缺点

会丢数据!

从原理我们就可以得知,Redis 并不会存储消息,那么如果生产者发布消息的时候,消费者宕机了,当服务恢复时,其间生产者发送的消息就丢失了。

不仅是宕机会导致消息丢失,如果消费者消费过慢也有可能导致消息丢失。

在面试鸭《651. Redis 主从复制的实现原理是什么? 》这题中,提到了 client-output-buffer-limit 参数,默认 pubsub 配置的是 32mb 8mb 60,即缓冲区一旦超过 32 MB 或持续 60s 超过 8M 直接把消费者下线。

Redis 虽然不会存储消息,但是消息会先写入这个缓冲区,供消费者拉取消费。如果消费者处理太慢,导致这个缓冲区溢出,那么消费者被强行下线,消息也就丢了。

Redis 发布/订阅模型应用场景

Redis 的哨兵集群和 Redis 实例通信用的就是发布/订阅模型。

一般业务上的即时通信场景也可以使用,但是由于消息会丢失,大部分情况下还是会使用消息队列中间件来实现发布/订阅。

Comments