redis subscribe无法接收离线消息是设计使然,因其本质为纯内存广播机制,不持久化、不维护消费位点、不缓存历史消息,断连后重连仅接收新消息。

Redis 的 SUBSCRIBE 无法接收离线消息,不是配置或代码写错了,而是设计如此 —— 它压根不存消息。
Pub/Sub 本质是内存广播,不是消息队列
发布者调用 PUBLISH,Redis 立刻把消息拷贝给所有当前在线的订阅者连接,然后丢弃。整个过程不写磁盘、不维护消费位点、不记录谁在线谁掉线。
- 客户端断开(网络抖动、进程重启、切后台),
SUBSCRIBE连接就断了,Redis 不会缓存任何东西等它回来 - 重连后执行
SUBSCRIBE news,只是重新加入“未来消息”的广播名单,历史消息早已蒸发 -
PUBLISH返回值为0就代表:此刻没有活跃订阅者,这条消息彻底消失
常见误判场景和验证方式
很多问题表面是“收不到”,实际是机制误解。先用 redis-cli 快速确认行为是否符合预期:
- 终端 A 执行
SUBSCRIBE order.status→ 进入阻塞监听 - 终端 B 执行
PUBLISH order.status "paid"→ 终端 A 立刻输出 - 此时 Ctrl+C 终止终端 A,再启动新终端 A’ 执行同样
SUBSCRIBE,之前那条"paid"永远不会出现
如果这步复现失败(比如新订阅者收到了旧消息),说明你连的不是纯 Pub/Sub,而是混用了 Stream 或其他中间层封装。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
哪些场景下你以为需要“离线消息”,其实不该用 Pub/Sub
只要业务要求“不能丢”“要补发”“需按序处理”,SUBSCRIBE 就不是解法,强行加重试或本地缓存只会掩盖问题:
- 外卖订单状态变更(支付→出餐→配送):漏一条就导致骑手没单可送
- 客服系统用户消息:用户切后台 2 分钟,回来发现没收到新咨询
- 后台任务触发(如定时结算):服务重启期间的
PUBLISH全部丢失,无人感知
这些必须换用 Stream(XADD/XREAD)或外部 MQ;Pub/Sub 只能当“实时扩音器”,负责把刚发生的事件吼给所有还在线的人听。
真正想保留离线消息,得绕开 SUBSCRIBE 自己管存储
没有银弹,但有明确路径:用 Stream 存消息,用 Pub/Sub 做轻量通知。
- 发布端:先
XADD order_stream * status "paid"写入流,再PUBLISH order.notify "new"广播“有新消息” - 订阅端:连接后先
XREAD COUNT 10 STREAMS order_stream $拉取未读,再SUBSCRIBE order.notify监听后续实时通知 - 关键点:
Stream的消费者组(XGROUP)才能保证每条消息至少被一个实例处理;单纯XREAD无组名=自己维护 offset,容易重复或跳过
最易忽略的是:Pub/Sub 的频道名大小写敏感、不支持通配符匹配历史数据、也没有 TTL 控制——它连“临时存一秒”都不做。接受这点,才能不把时间浪费在给广播机制加“持久化补丁”上。










