ssubscribe 能减少集群流量,因为它只在目标 slot 节点上建立连接并投递消息,避免传统 subscribe 的全节点广播,6 节点集群中将跨节点转发从 5 次降至 0 次。

SSUBSCRIBE 为什么能减少集群流量
传统 SUBSCRIBE 在 Redis Cluster 中会触发全节点广播:只要任意节点收到 PUBLISH,它就得把消息发给所有其他节点,再由各节点判断“我本地有没有这个订阅者”。6 节点集群里发 1 条消息,实际产生 5 次跨节点转发,网络和 CPU 开销随节点数线性上涨。
SSUBSCRIBE 不走这套逻辑——它只在目标 slot 所在节点上建立连接、接收和投递。消息路由由分片键(shard key)决定,不依赖 channel 名本身,也不广播。
- 必须显式启用:
shard-subscribe-enabled yes,否则SSUBSCRIBE命令直接报错 - 订阅只生效于当前连接的节点;如果客户端连的是非目标节点,
SSUBSCRIBE ch 1001会被拒绝,提示MOVED或ASK - 一个 channel 可以被多个分片键使用(如
SPUBLISH order:1001 1001 "ok"和SPUBLISH order:2002 2002 "ok"),但每个分片键只绑定一个 slot,天然隔离
SPUBLISH 与 PUBLISH 的参数和语义差异
PUBLISH 是无状态的单参数命令:PUBLISH ch:message "payload";而 SPUBLISH 强制要求第二个参数为分片键,格式是 SPUBLISH <channel><shard-key><message></message></shard-key></channel>。少传或错传都会报 ERR wrong number of arguments。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 分片键决定 slot:Redis 对
<shard-key></shard-key>做 CRC16 哈希,映射到 16384 个 slot 中的一个,跟 channel 名无关 - channel 名只是逻辑标识,不参与路由;你可以用
SPUBLISH user:notify 1001 "hi"和SPUBLISH system:alert 1001 "down"让两条不同语义的消息落到同一节点,便于聚合处理 - 不支持通配符:
PSUBSCRIBE无法用于 Sharded 模式,因为通配匹配无法预计算 slot
混用 SUBSCRIBE 和 SSUBSCRIBE 的后果
两者完全隔离:订阅 SSUBSCRIBE ch 1001 的客户端,收不到 PUBLISH ch "msg";反过来,SUBSCRIBE ch 也收不到 SPUBLISH ch 1001 "msg"。这不是 bug,是设计使然。
- 消息分裂:业务中若一部分服务用
SPUBLISH,另一部分仍用PUBLISH,会导致通知漏发——比如订单服务发SPUBLISH order:123 123 "paid",但风控服务还在SUBSCRIBE order:123,就永远收不到 - ACL 权限需单独配置:
SPUBLISH和SSUBSCRIBE是独立命令,旧 ACL 规则不自动覆盖,要加+ssubscribe、+spublish等权限项 - 监控指标不互通:
pubsub_channels只统计传统订阅数;查分片订阅得用PUBSUB SHARDCHANNELS或info cluster里的sharded_pubsub_channels
容易被忽略的部署前提
Sharded Pub/Sub 不是开箱即用的功能,几个硬性条件缺一不可:
- Redis 服务端必须是 7.0+ 且配置了
shard-subscribe-enabled yes - 客户端驱动必须支持新命令:redis-py ≥ 4.6.0、Lettuce ≥ 6.3.0、jedis ≥ 4.4.0;老版本调用
ssubscribe()会解析失败或抛unknown command - 分片键必须业务可控:不能用随机值或时间戳,否则失去保序和局部性;典型做法是复用用户 ID、订单 ID、设备 ID 这类天然分片维度
- 如果你需要“所有节点都收到某条消息”,Sharded 模式就不适用——得退回到单节点部署 + 传统 Pub/Sub,或改用
Stream+ 消费组










