3. 常见分布式事务方案:TCC模式、Saga模式、本地消息表、可靠消息最终一致性
在分布式系统中,传统数据库的 ACID 事务无法跨服务边界生效。本章聚焦四种主流分布式事务方案,从原理、适用场景到压测安全权限设计的关注点进行对比分析。理解这些方案的差异,是后续构建压测场景库与权限模型的基础。
3.1 方案总览与对比
四种方案在一致性保证、侵入性、性能与回滚能力上各有侧重。下表从核心维度进行横向对比:
| 方案 | 一致性模型 | 业务侵入性 | 回滚能力 | 典型延迟 | 压测关注点 |
|---|---|---|---|---|---|
| TCC 模式 | 强一致性(最终一致) | 高(需实现 Try/Confirm/Cancel) | 强(Cancel 阶段显式回滚) | 低(2次 RPC) | 幂等性、空回滚、悬挂 |
| Saga 模式 | 最终一致性 | 中(需实现正向/补偿事务) | 强(补偿事务回滚) | 中(异步编排) | 补偿幂等、状态机并发 |
| 本地消息表 | 最终一致性 | 低(依赖本地事务+定时任务) | 弱(需手动补偿) | 高(轮询间隔) | 消息积压、重复投递 |
| 可靠消息最终一致性 | 最终一致性 | 中(依赖消息中间件) | 中(消息重试+死信) | 中(异步消息) | 消息顺序、事务状态表 |
压测安全提示: 在集成测试压测场景中,TCC 的 Cancel 与 Saga 的补偿事务是权限校验的高危区——回滚操作若未做鉴权,攻击者可利用回滚接口破坏数据一致性。
3.2 TCC 模式(Try-Confirm-Cancel)
TCC 将分布式事务拆分为三个阶段,每个参与者服务都需要实现对应的接口。其核心思想是“预留资源 → 确认使用 → 取消预留”。
- Try 阶段: 尝试执行业务,完成资源预留或检查。例如,冻结库存、预扣余额。
- Confirm 阶段: 如果所有参与者 Try 成功,则全局协调器调用 Confirm 完成实际业务操作。
- Cancel 阶段: 如果任一参与者 Try 失败或超时,则调用 Cancel 释放预留资源。
以下 SVG 展示了 TCC 三阶段的典型调用流程:
压测场景库设计要点:
- 幂等性压测: 对 Confirm 和 Cancel 接口重复调用,验证幂等锁是否生效。
- 空回滚压测: 模拟 Try 未执行但 Cancel 被调用的情况,验证服务不报错。
- 悬挂压测: 模拟 Cancel 先于 Try 到达,验证资源状态机正确处理。
3.3 Saga 模式
Saga 模式通过将一个长事务拆分为多个本地事务,每个本地事务对应一个补偿事务。当某个本地事务失败时,按逆序调用补偿事务进行回滚。Saga 分为两种编排方式:
- Choreography( choreography): 每个服务在完成本地事务后,发布事件触发下一个服务。无中心协调器。
- Orchestration(编排): 由一个协调器(Orchestrator)负责通知各服务执行正向或补偿操作。
以下 SVG 展示了基于编排的 Saga 执行流程:
安全权限设计警告: Saga 的补偿事务接口必须与正向事务接口具有同等级别的权限校验。压测中常见的安全漏洞是补偿接口未做鉴权,导致攻击者可以绕过正向流程直接调用补偿,造成数据错乱。
3.4 本地消息表
本地消息表方案将分布式事务拆解为“本地事务 + 消息表 + 定时任务”。核心思路是:业务操作与消息写入在同一个本地事务中完成,然后通过定时任务轮询消息表,将消息投递给下游服务。
- 优点: 不依赖消息中间件的事务特性,实现简单,适合中小规模系统。
- 缺点: 消息表与业务库耦合,定时轮询存在延迟,且需要处理消息重复投递。
压测场景库设计要点:
- 消息积压压测: 模拟下游服务处理缓慢,观察消息表行数增长与定时任务消费能力。
- 重复投递压测: 模拟定时任务重复扫描,验证下游服务的幂等性。
- 数据库锁竞争压测: 高并发下消息表行锁与业务表行锁的相互影响。
3.5 可靠消息最终一致性
该方案通过消息中间件(如 RocketMQ、Kafka)的事务消息或半消息机制,保证本地事务与消息发送的原子性。典型流程如下:
- 生产者发送半消息(prepare)到 MQ,MQ 返回消息 ID。
- 生产者执行本地事务。
- 根据本地事务结果,提交(commit)或回滚(rollback)半消息。
- MQ 投递已提交的消息给消费者;若超时未确认,MQ 主动回查生产者事务状态。
下表对比了本地消息表与可靠消息最终一致性方案的关键差异:
| 对比维度 | 本地消息表 | 可靠消息最终一致性 |
|---|---|---|
| 消息存储 | 业务数据库的消息表 | 消息中间件内部存储 |
| 事务保证 | 依赖本地数据库事务 | 依赖 MQ 事务消息/半消息机制 |
| 延迟 | 高(定时轮询间隔) | 低(异步实时投递) |
| 扩展性 | 差(消息表与业务库耦合) | 好(MQ 可水平扩展) |
| 压测重点 | 数据库连接池、轮询 SQL 性能 | MQ 吞吐、回查接口性能 |
压测安全提示: 可靠消息方案中,MQ 的回查接口(check callback)是安全权限设计的薄弱环节。压测时需验证回查接口是否做了身份校验,防止攻击者伪造回查请求导致事务状态错误。
3.6 方案选型与压测策略总结
在集成测试压测场景库建设中,方案选型直接影响压测脚本的设计粒度:
- TCC: 适合对一致性要求高、业务资源可预扣的场景(如库存、账户)。压测需重点覆盖 Cancel 路径的并发与幂等。
- Saga: 适合长流程、异步化场景(如订单履约、旅游预订)。压测需关注编排器状态机在高并发下的正确性。
- 本地消息表: 适合中小团队、对延迟不敏感的场景。压测需关注消息表与业务表的锁竞争。
- 可靠消息最终一致性: 适合高吞吐、对一致性要求中等的场景。压测需关注 MQ 集群的吞吐与回查接口的性能。