Redis Pub/Sub不保证消息不丢失,必须改用STREAM;因其纯内存广播、无队列、无offset、不持久化,断连期间消息彻底丢弃,重连后无法补漏。

Redis 的发布订阅(Pub/Sub)模式天然支持一对多消息广播,不需要额外配置或中间层——只要多个客户端 SUBSCRIBE 同一个频道,PUBLISH 一条消息就会被实时推送给所有在线订阅者。
为什么 SUBSCRIBE 后客户端会“卡住”?
这是 Redis Pub/Sub 的阻塞式设计决定的:SUBSCRIBE 命令执行后,客户端连接会进入“订阅状态”,不再响应其他命令(如 GET、SET),只接收推送消息。这不是 bug,而是协议要求。
- 必须用独立连接做订阅——不能和业务命令混用同一连接
- 使用
redis-cli测试时,看到Reading messages (press Ctrl-C to quit)是正常现象,不是卡死 - 在代码中(如 Go 的
redigo、Java 的RedisMessageListenerContainer),需启用专用 goroutine 或线程处理监听,否则主线程会被阻塞
PUBLISH 返回值 (integer) N 到底代表什么?
PUBLISH channel message 的返回值是整数,表示**当前时刻在线且已成功收到该消息的订阅者数量**。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 返回
0:说明此时没有客户端在订阅该频道(注意:不是“没人注册过”,而是“此刻无活跃订阅者”) - 返回
1或更大:仅反映推送成功的连接数,不保证消息被业务逻辑消费(比如监听器抛异常、反序列化失败,Redis 不感知) - 这个数字不包含通过
PSUBSCRIBE匹配到的订阅者——模式订阅者是否计入,取决于 Redis 版本;6.0+ 默认计入,但建议用PUBSUB NUMSUB channel显式确认
如何让多个服务实例都收到同一条通知?
关键在于“频道名统一 + 订阅动作独立”。比如微服务 A、B、C 都要响应配置变更,就约定频道为 config:updated,各自启动时执行:
SUBSCRIBE config:updated
- 每个服务必须建立自己的 Redis 连接并调用
SUBSCRIBE,不能共用连接(Redis 不允许多个SUBSCRIBE在同一连接上叠加) - Spring Data Redis 中,
RedisMessageListenerContainer内部会为每个MessageListener维护独立连接,所以多个addMessageListener()调用是安全的 - 如果用
PSUBSCRIBE config:*,要注意通配符匹配开销略高,且PUBSUB NUMPAT返回的是模式订阅总数,不是单频道订阅数
真正容易被忽略的点是:Pub/Sub 消息**零持久化、零重试、零确认**。客户端断连期间的消息永远丢失,没有任何补偿机制——这决定了它只适合“通知类”场景(如刷新本地缓存、触发轻量计算),绝不能用于订单、支付等需要可靠投递的业务。

















