可靠性与消费语义
可靠链路
任意一段只有超时结果时,都不能简单推断消息肯定成功或失败,因此重试需要幂等。
Publisher Confirm 与 Return
- Ack:Broker 接管了发布,不代表消费者已经处理;
- Nack:Broker 无法完成接管,生产者需要按策略重试;
mandatory+ Return:消息无法路由到 Queue 时退回生产者;- Confirm 和 Return 解决的问题不同,应同时处理。
发布方要为未确认消息保留关联 ID,并对超时、不确定响应和连接中断执行有限重试。
持久化边界
可靠持久化通常需要 Durable Exchange/Queue、Persistent Message、Publisher Confirm 和满足故障模型的 Quorum Queue。没有任何配置能保证所有灾难场景“100% 不丢”,必须明确 RPO/RTO。
Consumer Ack
| 操作 | 结果 |
|---|---|
| Ack | 删除已成功处理的 Delivery |
| Nack/Reject + requeue | 重新入队,可能立即再次投递 |
| Nack/Reject + 不 requeue | 丢弃或进入 Dead Letter Exchange |
| Connection/Channel 关闭 | 未 Ack 消息通常重新入队 |
Ack 应在业务副作用成功后执行。先 Ack 再写数据库可能丢业务;先写数据库再 Ack 可能重复写,因此消费者应使用唯一键、Inbox 表或条件更新实现幂等。
重试与死信
立即 requeue=true 可能形成高频循环。常见做法是把失败消息发到带 TTL 的重试 Queue,过期后通过 Dead Letter Exchange 返回原 Queue,并设置最大次数和最终 Parking Lot Queue。
死信原因包括拒绝且不重新入队、TTL 到期、超过 Queue 长度限制,以及 Quorum Queue 达到 Delivery Limit。
幂等
At-Least-Once 下重复是正常现象。可使用数据库唯一约束、Inbox/Processed Message 表、业务状态机条件更新或有明确过期边界的 Redis 原子去重。仅“先查再插”并非原子操作。