为什么需要分布式事务
在单体应用中,数据库事务的ACID特性由本地事务管理器轻松保障。但当系统演进到微服务架构后,一个业务操作往往跨越多个服务与数据库,这就要求我们在"分布式"的环境下依然保证数据的一致性——这正是分布式事务要解决的核心难题。
CAP定理与事务的取舍
CAP定理告诉我们,在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)三者最多只能同时满足两个。由于网络分区是不可避免的,实际工程中的一致性方案本质上都是在"一致性"与"可用性"之间做出权衡。BASE理论(Basically Available, Soft state, Eventual consistency)正是这一权衡的指导框架。
两阶段提交(2PC)
两阶段提交是最经典的分布式事务协议,分为投票(Voting)和提交(Commit)两个阶段:
阶段一(Prepare):协调者向所有参与者发送事务预处理请求,各参与者执行事务但不提交,将undo/redo日志写入持久化存储,然后向协调者返回"同意"或"中止"。
阶段二(Commit/Rollback):如果所有参与者都返回同意,协调者发送提交指令;任意参与者返回中止或超时,协调者发送回滚指令。
2PC的主要缺陷在于:同步阻塞(参与者在等待决议时持有锁资源)、协调者单点故障(如果协调者在阶段二崩溃,参与者将一直处于阻塞状态)、数据不一致风险(部分参与者收到提交指令而另一部分未收到)。
三阶段提交(3PC)
3PC在2PC之间引入了CanCommit预询问阶段,并加入了参与者超时机制,一定程度上缓解了阻塞问题,但实现复杂且无法彻底解决网络分区下的数据一致性问题,在工业界应用较少。
TCC(Try-Confirm-Cancel)
TCC是一种业务层面的补偿型事务方案,要求每个业务操作实现三个接口:
Try:资源检查与预留。比如转账时冻结转出账户的金额,而非真正扣款。
Confirm:执行真正的业务逻辑。冻结成功后实际扣款并转入目标账户,Confirm必须幂等。
Cancel:回滚Try阶段预留的资源。解冻账户金额,Cancel同样必须幂等并处理空回滚(Try未执行时Cancel不应报错)和悬挂(Cancel先于Try执行时要能正确处理)。
TCC的优势在于不依赖数据库锁,性能较高,但业务侵入性强,实现成本大。适用于对一致性要求高且事务流程较短的场景,如金融支付、积分扣减。
基于消息的最终一致性(可靠消息事务)
核心思想:将分布式事务拆解为本地事务 消息传递。具体流程:
1. 事务发起方执行本地事务,并在同一个事务中写入一条"待发送"的消息到本地消息表。
2. 将消息投递到消息队列(Kafka/RocketMQ)。
3. 消息消费方执行自己的本地事务,成功后确认消费。
4. 失败时利用消息队列的重试机制进行补偿。
该方案实现了BASE中的最终一致性,性能优秀且对业务侵入较小。关键是必须保证"投递消息"这一操作的原子性——这也是本地消息表和事务消息(如RocketMQ Half Message)要解决的问题。
Saga模式
Saga是一种长事务方案,将大事务分解为一系列本地事务,每个本地事务都有对应的补偿操作。分为两种编排方式:
编排式(Orchestration):中央协调器(Saga Orchestrator)按顺序调用各服务,失败时按逆序触发补偿逻辑。优点:逻辑集中管理;缺点:协调器成为中心点。
协同式(Choreography):各服务通过事件驱动方式协作,服务A完成后触发事件监听服务B执行,失败时发布补偿事件。优点:去中心化、松耦合;缺点:流程分散难以追踪调试。
Saga适合业务流程长、涉及服务多的场景。注意事项:补偿操作必须保证幂等;建议只读操作尽量前置以减少补偿范围;需要设计完善的日志和告警来监控Saga执行状态。
Seata框架实战
Seata是开源的分布式事务解决方案,支持AT、TCC、Saga和XA四种模式:
AT模式(Automatic Transaction):对业务零侵入,通过解析SQL自动生成镜像数据实现回滚,依赖数据库的本地事务能力。适用于基于关系型数据库的微服务场景。
Seata Server(TC):事务协调者,管理全局事务的生命周期,支持高可用部署(注册到Nacos、存储到DB或Redis)。
集成步骤:部署TC Server → 各RM引入Seata代理数据源 → 在业务入口添加@GlobalTransactional注解 → 配置undo_log表用于自动回滚。
工程选型建议
| 场景 | 推荐方案 | 一致性级别 |
| 跨服务数据强一致 | TCC / 2PC | 强一致 |
| 异步处理 最终一致 | 可靠消息队列 | 最终一致 |
| 长流程业务编排 | Saga(编排式) | 最终一致 |
| 微服务 关系型DB | Seata AT | 强一致 |
| 异构存储系统 | TCC / Saga | 依配置 |
总结
分布式事务没有银弹。强一致方案(2PC/TCC)通常以牺牲性能为代价,最终一致方案(消息/Saga)则需要在业务层面容忍短暂的不一致状态。实际选型时,应该从业务容忍度、性能要求、团队技术能力三个维度综合评估,优先采用"避免分布式事务"的设计手段(如合理的服务边界划分、CQRS、事件驱动架构等),再针对性地选择合适的事务方案。

发表评论 取消回复