PUB/SUB根本不支持消息持久化,因其是纯内存广播通道,无存储层、不写AOF/RDB、不维护消费状态;必须改用Redis Stream,通过XADD写入、XGROUP建组、XREADGROUP读取及XACK确认实现持久化与可靠投递。

PUB/SUB 根本不支持消息持久化——这不是配置没开、参数没设对,而是设计上就不存消息。只要没客户端在线,PUBLISH 返回成功,消息也已经蒸发了。
PUB/SUB 为什么连“存一下”都不做
-
PUB/SUB是纯内存广播通道:没有存储层,不写 AOF/RDB,不复制到从节点,也不进任何队列 -
SUBSCRIBE不记录 offset、不维护游标、不区分新老消息;断连重连后,之前发的全当没发生过 -
PUBLISH返回1只表示“至少一个当前在线订阅者收到了”,不代表落地、不触发重试、不进 PEL(Pending Entries List) - 常见现象:服务重启后订单通知消失、凌晨告警整批漏收、扩容新消费者实例收不到历史日志
必须换用 Redis Stream,不是加个 ACK 就能救
Redis Stream 是 Redis 5.0+ 提供的真正可落地的消息模型,它自带持久化、可回溯、需确认、支持多组消费:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 写入用
XADD:推荐XADD stream:events <em> event "paid" order_id "123"</em>,让 Redis 自动生成 ID(如1716649200000-0),天然有序可追溯 - 消费前必须建组:
XGROUP CREATE stream:events mygroup $ MKSTREAM,其中$表示从最新消息开始,MKSTREAM自动创建 stream(避免NOGROUP错误) - 拉取消息用
XREADGROUP:XREADGROUP GROUP mygroup consumer1 COUNT 10 STREAMS stream:events >,>是特殊符号,代表“上次未确认的下一条” - 处理完必须
XACK:XACK stream:events mygroup 1716649200000-0,否则该消息会一直卡在 PEL 里,下次还给你
容易踩的三个坑
-
XADD不加MAXLEN:消息无限堆积,磁盘爆满或XLEN查询变慢;建议写成XADD stream:logs MAXLEN ~ 10000 * ...,~表示近似修剪,性能更好 - 消费者第一次启动时用
>,想回溯就得换 ID:比如0-0从头读,或用时间戳 ID 如1716649200000-0跳到某时刻 -
XGROUP CREATE忘加MKSTREAM:stream 不存在时直接报错,而不是静默创建;生产环境必须带上
真正的不可靠点不在 Redis 版本,而在是否把 XACK 当成可选操作——只要漏掉一次,那条消息就会反复出现。

















