顺序、重复与事务消息:消息三保难题
2026/8/24大约 3 分钟
亿级规模系统系列 · 阶段 3 · 异步与消息 · 第 18/49 篇 · 🚧 占位待学
上一篇:《亿级消息存储模型:CommitLog、零拷贝与页缓存》
下一篇:《消息堆积治理:十亿条积压怎么办》
学习大纲:《QPS 过万与亿级消息系统设计学习总纲》
状态:待学习。 本文为占位文档:知识点清单、实验与验收标准已就绪,正文待按「先学习、先实验、再撰写」补全。
对应总纲单元:阶段 3 · 单元 3.4
一、本文要解决的问题
分布式消息有三个绕不开的「保」:保顺序(订单先创建后支付,乱了业务就错)、保不重(重试导致一条消息消费两次,用户扣两次钱怎么办)、保一致(发消息和写库要么都成要么都不成)。三者不可兼得是物理现实,工程的任务是把「违和感」降到业务可接受。
二、知识点清单
- 顺序的层级:全局有序(单队列,牺牲并发)vs 局部有序(同一 key 同一队列,生产可用)——RocketMQ 顺序消息与 Kafka 分区键的本质
- 重复的来源:发送重试、消费 ack 超时重投——至少一次投递(at-least-once)的现实
- 消费端幂等三种实现:去重表(唯一索引)、状态机(状态前置校验)、业务天然幂等(set 覆盖)
- 「至少一次 + 幂等 = 恰好一次效果」:为什么不在投递层解决而在消费端解决
- 发送一致性问题:本地事务成功但消息丢 / 消息发出但本地事务回滚——两种不一致时序
- RocketMQ 事务消息:half message → 本地事务 → commit/rollback → 回查兜底;与本地消息表的对比
三、动手实验(学习时必须真跑)
- 构造发送端超时重试场景,复现同一条业务消息被消费两次;加去重表实现幂等后再验证
- RocketMQ 顺序消息 demo:同一订单的多条消息(创建 → 支付 → 发货),验证局部有序;乱发(非顺序发)时观察乱序现象
- 事务消息实验:本地事务里故意抛异常 / sleep 超时,观察 broker 回查与最终 rollback
四、验收标准(全部通过才进入下一篇)
五、写作提示(补正文时遵守)
- 开篇问题驱动;结构走「是什么 → 为什么 → 怎么做 → 背景知识」
- 所有代码、命令、输出必须先在本机跑通再写入,不得杜撰
- 版本口径以总纲环境清单为准(Spring Boot 3.x / MySQL 8.0 / Redis 8.x / RocketMQ 5.3.x / Kafka 4.3 / ShardingSphere 5.5.3)
- 涉及版本敏感结论时标注出处与时间
本篇完成后,把文首导航块的「🚧 占位待学」去掉,并在总纲处打卡。