登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis 分片 Pub/Sub 与普通 Pub/Sub 有什么区别

来源:17golang原创

时间:2026-09-28 00:52:44 327浏览 收藏

Redis 分片 Pub/Sub 与普通 Pub/Sub 有什么区别

如果你只需要让集群里的所有节点都听到一条广播,普通 Pub/Sub 更直接;如果消息只应该在某个分片范围内传播,分片 Pub/Sub 更合适。两者最关键的差别不是命令名字,而是集群总线上的传播范围:普通 Pub/Sub 面向整个集群,分片 Pub/Sub 面向频道哈希到的 shard。

官方文档:https://redis.io/docs/latest/develop/pubsub/

一句话判断:跨租户、跨分片的全局通知选普通 Pub/Sub;按租户、业务分片或局部节点隔离的事件选分片 Pub/Sub。两者都采用 at-most-once 语义,不能直接替代需要持久化、重放或确认的消息队列。
  • 普通 Pub/Sub:消息会向集群各节点传播,广播范围大,使用 SUBSCRIBE、PUBLISH。
  • 分片 Pub/Sub:频道按键槽算法映射到 shard,只在该 shard 内转发,使用 SSUBSCRIBE、SPUBLISH。
  • 可靠性边界:订阅端断开或处理失败时消息不会自动补发,需要重放就改用 Redis Streams。

先看两种广播路径再选命令

我第一次把 Redis Cluster 的 Pub/Sub 接入多租户事件时,容易把“客户端连到哪个节点”和“消息应该传播到哪里”混为一谈。普通 Pub/Sub 的频道不按 key slot 限定,发布后会在集群范围传播;订阅客户端可以连到任意合适的节点,但付出的代价是集群总线要承载全局扩散。

Redis 7.0 引入分片 Pub/Sub 后,shard channel 使用与 key 相同的槽计算方式。发布分片消息时,客户端应把请求送到拥有该频道槽位的节点;集群再把消息转给该 shard 中的节点。订阅端可以连接负责该槽位的主节点,也可以连接它的副本。

普通 Pub/Sub 全局传播与分片 Pub/Sub 槽内传播的静态关系说明图
图1:传播范围说明图,左侧表示普通 Pub/Sub 的全局边界,右侧表示分片 Pub/Sub 的 slot 与 shard 边界;这是静态说明图,不是运行截图。

最小命令对照可以这样记:

# 普通 Pub/Sub:全局事件由所有订阅者接收
redis-cli -c -h redis-node-a SUBSCRIBE config:invalidate
redis-cli -c -h redis-node-b PUBLISH config:invalidate "reload"

# 分片 Pub/Sub:同一 shard 内的订阅者接收消息
redis-cli -c -h redis-node-a SSUBSCRIBE tenant:{42}:event
redis-cli -c -h redis-node-a SPUBLISH tenant:{42}:event "order-created"

上面的命令是结构示例,不代表已经在本机执行。带花括号的频道名只是为了让同一业务分区拥有稳定的 hash tag;实际命名仍要结合客户端的 cluster 路由能力。不能因为两个客户端连接到了同一台机器,就推断普通 Pub/Sub 已经变成了分片广播。

哪些场景该用普通 Pub/Sub

全局配置失效、统一刷新本地缓存、集群级运维通知,通常需要每个相关实例都收到消息。这类事件的关注点是“所有订阅者都知道”,普通 Pub/Sub 的语义更贴近需求,也不需要额外设计频道到业务分片的映射。

代价是传播面不可按租户缩小:集群节点越多、频道越活跃,集群总线上的复制和转发压力越明显。普通 Pub/Sub 适合低延迟广播,不适合把大量细粒度租户事件无差别地推给整个集群。频道前缀可以做环境隔离,但它不会改变普通 Pub/Sub 的全局传播性质。

哪些场景该用分片 Pub/Sub

如果消息只属于一个租户、一个业务分区或一组固定的热点数据,分片 Pub/Sub 可以把传播限制在目标 shard。这样做的收益不是“消息更可靠”,而是减少不相关节点接收和转发消息,让 Pub/Sub 的吞吐更容易随 shard 横向扩展。

采用前要确认三件事:频道是否能稳定映射到业务分区;客户端是否支持 SSUBSCRIBE、SUNSUBSCRIBE、SPUBLISH;发布者是否能正确路由到频道槽位。若一个事件必须被所有租户消费,硬拆成多个 shard channel 反而会增加发布和订阅管理复杂度。

判断维度普通 Pub/Sub分片 Pub/Sub
传播范围集群级目标 shard
典型命令SUBSCRIBE / PUBLISHSSUBSCRIBE / SPUBLISH
适合事件全局配置、统一失效通知租户或分区内事件
主要代价集群总线传播面更大需要设计分片频道和路由

可靠性与选型边界

普通 Pub/Sub 和分片 Pub/Sub 都是 at-most-once:Redis 把消息推给订阅端后,不会因为网络断开、消费者异常或处理失败而自动补发。它们适合“丢一条也能通过下一次状态同步恢复”的通知,不适合订单状态、计费事件或必须审计的业务事实。

Redis Pub/Sub 的 at-most-once 边界与 Streams 持久化关系说明图
图2:可靠性边界说明图,展示 Pub/Sub 的一次推送、断线丢失与 Redis Streams 持久化重放之间的关系;这是静态说明图,不是运行截图。

如果消费者需要确认、重放、按消费组推进或在故障后补读,应把事件写入 Redis Streams,再根据实时通知需求额外发送 Pub/Sub。也就是说,普通与分片 Pub/Sub 解决的是“消息传播到哪里”,Streams 解决的是“消息留下来后如何再次消费”,不要用缩小传播范围来掩盖可靠性缺口。

常见问题

分片 Pub/Sub 是否比普通 Pub/Sub 更可靠?不是。它主要改变集群传播范围,仍然是 at-most-once。

普通 Pub/Sub 能按 Redis 数据库编号隔离吗?不能。Pub/Sub 与 key space 和数据库编号无关;需要环境隔离时,应把环境信息放入频道命名,并在业务侧做权限和订阅约束。

总结

先问消息要覆盖整个集群还是只覆盖一个业务 shard,再决定命令:全局广播用普通 Pub/Sub,局部事件用分片 Pub/Sub;一旦需求出现持久化、确认或重放,就把 Redis Streams 纳入方案。这个顺序比单纯比较两个命令的性能更可靠。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>