返回首页

Redis核心2.3: 发布订阅机制入门与实践

适用版本:Redis 7.2.x

Redis 除了做缓存、计数器、排行榜之外,还内置了一套非常轻量的消息通信机制——发布订阅(Pub/Sub)

如果你以前接触过消息队列,可能会把 Redis 的发布订阅理解为“简化版的消息广播”。这个理解基本没问题:

  • 发送方把消息发布到某个频道
  • 订阅方订阅这个频道
  • 只要频道上有新消息,订阅者就能立即收到

它非常适合做轻量、低门槛、实时性高的通知型场景,比如:

  • 配置变更广播
  • 聊天室消息分发
  • 简单事件通知
  • 服务间轻量信号传递

但与此同时,它也有明显边界:它不是可靠消息队列。理解这一点,比背命令更重要。


一、什么是发布订阅机制

发布订阅(Publish / Subscribe)的核心思想是“解耦消息发送者与接收者”。

在 Redis 中主要有三个角色:

  • 发布者(Publisher):负责发送消息
  • 频道(Channel):消息投递的主题
  • 订阅者(Subscriber):订阅频道并接收消息

举个例子:

  • 频道名:news.tech
  • 发布者:业务服务 A
  • 订阅者:服务 B、服务 C、调试客户端

只要服务 A 向 news.tech 发布消息,所有在线订阅 news.tech 的客户端都会收到。


二、Redis Pub/Sub 的工作方式

1. 基本流程

Redis 发布订阅的工作流程可以概括为:

  1. 订阅者使用 SUBSCRIBE channel 订阅某个频道
  2. 发布者使用 PUBLISH channel message 向频道发送消息
  3. Redis 把消息实时推送给当前在线的订阅者

注意这里有一个关键词:当前在线

Redis Pub/Sub 不会像传统消息队列那样把消息持久保存起来,离线期间错过的消息,订阅者上线后是收不到的。

2. 它不是“先存后投”

这是初学者最容易误解的地方。

Redis Pub/Sub 更像“广播喇叭”,不是“消息仓库”。

  • 有人在线听,就能听到
  • 没人在线听,消息就直接过去了
  • 不会自动补发历史消息

因此它适合通知,而不适合必须可靠送达的业务消息。


三、常用命令与示例

1. 基础订阅与发布

我们可以用两个终端来演示。

终端 A:订阅频道

redis-cli
127.0.0.1:6379> SUBSCRIBE order.created
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "order.created"
3) (integer) 1

终端 B:发布消息

redis-cli
127.0.0.1:6379> PUBLISH order.created "order_id=1001"
(integer) 1

此时终端 A 会收到:

1) "message"
2) "order.created"
3) "order_id=1001"

2. 订阅多个频道

SUBSCRIBE order.created order.paid order.cancelled

这样一个连接就可以同时接收多个频道的消息。

3. 模式订阅

Redis 支持按模式订阅:

PSUBSCRIBE order.*

当有以下频道发布消息时:

  • order.created
  • order.paid
  • order.cancelled

都能被这个订阅者接收到。

4. 查看 Pub/Sub 状态

PUBSUB CHANNELS
PUBSUB NUMSUB order.created
PUBSUB NUMPAT

这些命令可以帮助我们查看:

  • 当前有哪些频道
  • 某个频道有多少订阅者
  • 当前有多少模式订阅

四、Redis 7.x 中的分片发布订阅

在 Redis 7.x 中,还引入了 Sharded Pub/Sub(分片发布订阅),用于更适配集群环境。

常见命令有:

SSUBSCRIBE shard:notice
SPUBLISH shard:notice "hello"
SUNSUBSCRIBE shard:notice

它与普通 Pub/Sub 的主要区别在于:

  • 普通 Pub/Sub 更偏向全局频道广播
  • 分片 Pub/Sub 会结合槽位路由,更适合 Redis Cluster 场景

如果你当前仍然是单机或主从架构,先掌握普通 SUBSCRIBE / PUBLISH 即可;如果在 Redis Cluster 中设计广播能力,再进一步理解 SSUBSCRIBE / SPUBLISH 会更合适。


五、Pub/Sub 的特点与边界

1. 优点

Redis 发布订阅的优点很明显:

  • 使用简单,命令非常少
  • 延迟低,适合实时通知
  • 无需单独部署消息中间件
  • 对轻量级通知场景很方便

2. 局限性

但它的边界也同样明显:

  • 消息不持久化
  • 不保证可靠投递
  • 订阅者离线会丢消息
  • 没有消费确认机制
  • 不适合复杂消息堆积与回溯场景

所以在设计业务时,千万不要把 Redis Pub/Sub 直接等同于 Kafka、RocketMQ 或 RabbitMQ。


六、配置与命令实践示例

1. 用于配置变更广播

比如后台系统更新了某项配置,希望多个应用实例立即感知:

PUBLISH config.reload "feature_x=true"

各个应用实例订阅:

SUBSCRIBE config.reload

收到消息后,应用主动重新加载本地缓存配置。

2. 用于简单聊天室消息分发

PUBLISH chat.room.1001 "user=tom: hello"
SUBSCRIBE chat.room.1001

这种做法适合原型验证或轻量实时通信,但如果要求历史消息、离线补偿、已读回执,就不适合只用 Pub/Sub。

3. 检查频道订阅情况

PUBSUB CHANNELS
PUBSUB NUMSUB chat.room.1001

如果你发现消息发出去了但没人收到,第一步就可以先检查:当前是否真的有订阅者在线。


七、常见问题

1. 为什么发布成功了,但订阅者没有收到?

常见原因有:

  • 订阅者并不在线
  • 订阅的是另一个频道名
  • 使用了模式订阅,但模式不匹配
  • 客户端连接被复用或中断
  • 在集群模式下对频道路由理解有误

PUBLISH 返回值表示收到该消息的订阅者数量,如果返回 0,通常说明当前没有匹配订阅者在线。

2. 订阅连接还能执行普通命令吗?

通常不建议。

一旦客户端进入订阅模式,这个连接主要用于接收消息。实践中通常会:

  • 普通业务命令使用一个连接池
  • Pub/Sub 单独使用订阅连接

这样更清晰,也更稳定。

3. Pub/Sub 能不能保证消息不丢?

不能。

如果业务要求:

  • 消息必须送达
  • 消费失败可重试
  • 能查看历史消息
  • 支持消费组

那么应该考虑 Redis Streams 或专业消息队列,而不是单纯依赖 Pub/Sub。

4. Redis Pub/Sub 和 Streams 有什么区别?

一个简单理解方式:

  • Pub/Sub:实时广播,轻量,但不可靠
  • Streams:可保存消息、可回放、可消费组,适合更正式的消息处理场景

八、实践建议

1. 把 Pub/Sub 用在“通知”,不要硬扛“可靠消息”

适合的场景:

  • 配置刷新通知
  • 缓存失效广播
  • 简单事件提醒
  • 低价值、可丢失的实时信号

不太适合的场景:

  • 订单消息主链路
  • 支付结果投递
  • 库存扣减通知
  • 必须审计与回放的业务事件

2. 订阅连接要独立管理

不要把订阅连接和普通 Redis 读写连接混用。更常见的做法是:

  • 一个连接专门负责订阅
  • 收到消息后交给业务线程池处理
  • 普通 Redis 访问仍走独立连接池

3. 消息体尽量简单,必要时只传 ID

Pub/Sub 消息更适合传递轻量内容。实践中常见模式是:

  • 消息里只发对象 ID 或事件类型
  • 消费端收到后再去查询详细数据

这样可以降低消息耦合,也能减小消息体积。

4. 集群环境提前确认是否需要分片 Pub/Sub

如果你使用 Redis Cluster,并且对广播范围、路由成本、槽位行为有明确要求,可以进一步考虑 SPUBLISH / SSUBSCRIBE。但如果只是入门和一般通知场景,先把普通 Pub/Sub 理解透更重要。

5. 重要链路优先考虑 Streams 或专业 MQ

如果你发现自己开始需要:

  • 消费确认
  • 失败重试
  • 死信处理
  • 消息积压
  • 顺序消费
  • 历史回放

那就说明场景已经超出 Pub/Sub 的舒适区了。


九、小结

Redis 发布订阅机制非常适合作为入门级、轻量级的消息广播方案。学习它时,建议重点记住以下几点:

  1. Pub/Sub 的本质是实时广播,不是可靠队列
  2. 消息只会发给当前在线订阅者,离线不会补发
  3. SUBSCRIBE / PUBLISH 适合轻量通知,SSUBSCRIBE / SPUBLISH 适合集群分片场景
  4. 一旦业务要求可靠性、可回放、可重试,就应该考虑 Streams 或更专业的 MQ

如果把 Redis Pub/Sub 用在它擅长的地方,它会非常顺手;如果把它当成完整消息中间件来使用,就容易踩坑。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

Redis核心2.2: 过期键与内存淘汰机制

下一篇

Redis核心2.4: 持久化与内存配置实践手册