Redis发布订阅不适合做可靠消息队列,因其无消息持久化、无ACK确认、不保证顺序、断连即丢消息;适合低延迟广播场景,如配置变更通知、用户上下线同步、实时日志聚合、聊天室消息透传;禁用于订单扣库存、支付回调等强可靠性场景。

Redis 发布订阅模式不适合做可靠消息队列,但特别适合「不保证送达、不需重试、强调低延迟广播」的实时通知类场景。
哪些业务场景能直接用,哪些不能碰
能用的典型场景包括:
- 服务间轻量事件广播(如配置变更通知、灰度开关刷新)
- 用户在线状态同步(如“用户上线/下线”广播到所有网关实例)
- 实时日志聚合推送(如将各节点错误日志统一推送到监控侧)
- 前端长连接消息透传(如聊天室新消息、订单状态变更广播给所有已连接客户端)
不能用的场景必须避开:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 订单创建后扣减库存——
PUBLISH失败无重试,消息丢了就没了 - 支付结果回调——没有 ACK 机制,无法确认下游是否收到
- 需要严格顺序或 Exactly-Once 语义的流程——Redis Pub/Sub 不保证消息顺序,也不支持消费位点管理
为什么 Java 项目里常配 RedisMessageListenerContainer 却又不敢全靠它
因为它的生命周期和线程模型有隐性约束:
-
RedisMessageListenerContainer默认使用单线程处理所有频道消息,高并发时容易堆积;需显式配置taskExecutor才能并行消费 - 监听器抛出未捕获异常会导致整个容器停止监听,必须在
onMessage内包一层try-catch - 它不感知连接断开重连后的订阅恢复——Lettuce 客户端自动重连后,
subscribe不会自动重发,得自己监听ConnectionWatchdog事件手动补订
Node.js 用 subscriber.duplicate() 是必须的,不是可选的
这是最容易被忽略的底层约束:
- Redis 协议规定:一个连接一旦进入
SUBSCRIBE状态,就只能收消息,不能再发PUBLISH或其他命令 - 如果复用同一个
client实例既publish又subscribe,后续PUBLISH会卡住或报错ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed -
duplicate()创建的是独立连接,底层 TCP socket 和命令缓冲区完全隔离,这才是安全做法
真正难的不是怎么写订阅逻辑,而是判断“这个业务到底该不该走 Pub/Sub”——只要有一条消息不能丢、不能乱序、不能重复,就该立刻换 RocketMQ 或 Kafka。

















