redis pub/sub 没有死信队列,因其不存储消息、无消费状态追踪、无法确认接收成功;publish 后消息即焚,不落盘、无id、无ttl,连“是否丢失”都无法判断。

Redis Pub/Sub 为什么压根没有死信队列
因为 Pub/Sub 不是消息队列,它连“消息存储”这个基本前提都不满足——PUBLISH一执行,消息只在内存里走一圈 socket 推送,发完即焚,不落盘、不记 ID、不维护消费状态。死信队列(DLQ)的前提是:消息可定位、可重放、有失败标记;而 Pub/Sub 连“这条消息有没有被收到”都不知道,自然无法判断“该不该进 DLQ”。
-
PUBLISH返回值是订阅者数量,不是发送成功状态;返回0表示此刻没人在线,消息直接丢弃,无日志、无回调、无补偿 - 没有消息 ID、没有时间戳、没有 TTL,连“哪条消息失败了”都无从查起
- 客户端断连后重连,
SUBSCRIBE是全新连接,Redis 不保留任何历史订阅上下文 - 集群模式下,
SUBSCRIBE只作用于单个节点,MOVED 错误会让订阅逻辑彻底失效
生产环境遇到消息“疑似丢失”该怎么查
别急着加重试或改代码,先确认是不是 Pub/Sub 本职工作没干好。常见假性丢消息其实是配置或使用姿势问题。
- 用
redis-cli PUBSUB NUMSUB channel_name看实时订阅数,不是 0 才说明有人在听;返回 0 却以为“发出去了”,其实是白发 - 用
CLIENT LIST检查订阅连接的flags字段:如果大量是N(非阻塞),说明连接已异常但未断开,消息正卡在内核发送缓冲区(omem值高就是证据) - 用
PUBSUB CHANNELS *确认频道名拼写是否一致,大小写、冒号、空格都算不同频道 - PSUBSCRIBE 模式匹配时,
user.*.update不会匹配user.123.profile.update,通配符不支持递归
真需要死信能力,别硬改 Pub/Sub
强行给 Pub/Sub 加 DLQ,等于给自行车装涡轮增压——结构不支持,越补越崩。正确路径是换模型,不是调参数。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
- 轻量可靠场景:改用
Stream+XGROUP,配合XREADGROUP和XACK,失败消息会留在 pending list,可用XCLAIM主动捞回或转存到专门的dlq:stream - 中高可靠性场景:直接上 RabbitMQ/Kafka,原生支持死信交换器(DLX)、TTL、延迟投递,运维链路清晰
- 临时兜底方案:发布端把关键消息同时
LPUSH到一个backup:queue,消费者处理失败时主动触发LPOP+ 重试逻辑,但需自行管理幂等和过期 - 绝对禁止:在
SUBSCRIBE回调里做耗时操作(如 HTTP 调用),超时或异常会导致连接中断,后续消息全丢
最容易被忽略的坑:你以为的“重连”根本没重订阅
很多客户端库(比如早期版本的 redis-py)自动重连后,不会自动恢复 SUBSCRIBE 状态。连接重建了,但频道还是没人听——这比丢消息更隐蔽,因为日志里完全看不出异常。
必须显式监听断连事件,在重连成功后手动调用 SUBSCRIBE 或 PSUBSCRIBE,且要加重试和超时,避免因网络抖动反复失败卡死。更稳妥的做法是:每个订阅逻辑独占一个连接,并用独立心跳保活,别和其他命令混用同一个 Connection。










