redis pub/sub不适合做可靠消息队列,因其无消息持久化、不保证顺序、无重试机制,仅适用于实时广播场景。

Pub/Sub 能做即时推送,但不能当消息队列用——它不存消息、不保序、不重试,只适合“发了就不管”的广播场景。
订阅者必须保持长连接,断连后收不到历史消息
Redis Pub/Sub 的消息是纯内存转发,没有持久化。一旦客户端断开(比如网络抖动、进程重启),期间发布的所有消息就彻底丢失。
- 不要指望
SUBSCRIBE后还能补收离线消息;需要离线保障就得换Stream或加外部存储 - Node.js 中用
node-redis时,client.subscribe()后必须维持连接活跃,建议配合ping心跳或自动重连逻辑 - Python 的
redis-py默认不自动重连,断连后listen()会直接抛ConnectionError,得自己捕获并重建订阅
PUBLISH 返回值是关键指标,不是“发成功”而是“有人在听”
PUBLISH channel message 的返回值是整数,代表当前收到该消息的订阅者数量。这个数字为 0 并不意味着发送失败,只说明此刻没人订阅这个 channel。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 调试时先用
redis-cli PUBSUB NUMSUB channel_name确认订阅数是否为预期值 - 如果返回
0却预期有接收方,大概率是:频道名拼错、订阅者还没连上、或用了PSUBSCRIBE但发布用的是普通PUBLISH -
PUBSUB CHANNELS可列出所有至少有一个订阅者的频道,快速验证频道是否“活”着
模式订阅(PSUBSCRIBE)容易踩通配符陷阱
PSUBSCRIBE news.* 看似灵活,但 Redis 的通配符只支持 * 和 ?,不支持正则,也不支持嵌套匹配(比如 news.** 无效)。
-
PSUBSCRIBE user.*.update只能匹配user.123.update,不匹配user.123.profile.update - 多个
PSUBSCRIBE模式之间可能冲突:同时订阅user.*和user.123.*,发往user.123.update的消息会被触发两次回调 - 生产环境慎用
PSUBSCRIBE *,它会收到所有频道消息,极易打爆内存或 CPU
集群环境下不能直接用 SUBSCRIBE,得切到分片模式
Redis Cluster 不支持跨节点的 Pub/Sub,因为频道信息无法在分片间同步。直接对集群执行 SUBSCRIBE 会报错 MOVED 或只在单个节点生效。
- 必须使用支持分片的客户端,比如
node-redis@4.6+的sSubscribe()方法,底层走SSUBSCRIBE命令 - Java 的
lettuce需启用RedisClient.enableShardedPubSub(),否则订阅会静默失败 - 频道名本身不会被哈希路由,但分片订阅要求客户端主动连接到所有 master 节点并分别订阅——这意味着资源开销翻倍,别盲目扩节点
真正难的不是写通 SUBSCRIBE 和 PUBLISH,而是判断什么时候不该用它:比如需要消息确认、投递保证、消费进度管理,或者订阅者数量动态变化极大——这些时候,Stream 或 Kafka 才是更稳的选择。










