704 字
4 分钟
Redis Stream 如何保证消息消费?ACK 和 PEL 是什么?
Redis Stream 保存带 ID 的消息,消费组记录消费进度与未确认消息。相比简单 Pub/Sub,它允许消费者离线后继续读取、追踪处理中消息,并由其他消费者接管。这些机制有助于实现至少一次处理,不自动保证业务恰好执行一次。
一条消息经历什么?
生产者 XADD 写入消息;创建消费组后,消费者通过 XREADGROUP 读取新消息。未使用 NOACK 等特殊方式时,已投递但尚未确认的消息进入组内待确认列表 PEL。消费者成功完成业务后调用 XACK,从 PEL 移除相应记录,但不会因此自动删除 Stream 中的消息内容。
XADD jobs * type email user_id 1001XGROUP CREATE jobs workers 0 MKSTREAMXREADGROUP GROUP workers worker-1 COUNT 10 STREAMS jobs ># 实际完成业务后,对返回的具体消息 ID 执行 XACK例子选择从 0 开始建组,表示已有消息也可读取;从 $ 开始则关注创建时位置之后的新消息。这是一次性建组示例,已存在消费组时不能每次启动都不加处理地重复创建。
消费者宕机怎么办?
XPENDING 可观察待确认消息。对于长时间未完成的消息,可以按版本使用 XCLAIM 或 XAUTOCLAIM 接管,再处理并确认。接管阈值应超过正常处理时间,否则一个仍在工作的消费者与接管者可能重复执行。业务用消息 ID、订单号或唯一约束实现幂等,还应设置重试上限和失败处理渠道。
Stream 的持久性仍依赖 Redis 的持久化和复制配置。修剪与删除也要考虑未处理消息,不能只为了限制长度就无条件删除业务尚未消费的历史。
常见追问
处理完业务但 XACK 前宕机,会发生什么?
消息可能被再次接管,业务重复处理;幂等设计应能识别已经成功完成的操作。
先 XACK 再执行业务可以避免重复吗?
这会引入丢处理风险:确认后宕机,系统可能认为消息已完成,但业务未执行。通常先完成业务再确认,并处理重复。
Pub/Sub 为什么不适合可靠任务投递?
它主要是即时广播,不为离线订阅者保存消费积压,也没有相同的确认与接管机制;断开期间的消息不能靠重新订阅自动补回。
不同消费组之间会争抢同一条消息吗?
各组有自己的进度,可以独立消费同一 Stream。组内消费者分担工作,组间则可以分别实现日志、通知等不同职责。
Redis Stream 如何保证消息消费?ACK 和 PEL 是什么?
https://blog.xqcherry.top/posts/interview/redis/redis-streams-reliability/ 目录