什么是分布式事务
分布式事务 是指一个事务需要跨多个独立的系统或者服务执行,并确保这些操作以原子性,一致性,隔离性,持久性(ACID)为核心原则,要么全部完成(提交),要么全部回滚(失败)。在微服务架构中,分布式事务非常常见,因为不同的服务可能管理不同的资源(如数据库、消息队列等)。
分布式事务的挑战
- 网络系统故障:服务间的通信存在延迟或失败的风险。
- 系统故障:某些参与服务可能在事务中途发生故障。
- 一致性维护:需要确保所有服务对事务的状态达成一致,避免数据不一致。
- 性能开销:分布式事务会带来额外的锁管理和协调开销。
分布式事务常见的实现方式
- 两段式提交(2PC, Two-Phase Commit)
- 原理:将事务划分为两个阶段(准备和提交),通过事务管理器协调各参与方的操作。
A. 准备阶段
(1) 事务管理器向所有的服务发布准备(Prepare)请求
(2) 参与者执行本地操作,但是不提交,并记录日志
(3) 参与者反馈准备“成功”或是“失败”给事务管理者
B. 提交阶段
(1) 如果所有参与者返回“准备成功”,事务管理器发送提交请求(Commit),参与者提交本地事务
(2) 如果有任何一个参与者失败,事务管理器发送回滚请求(Rollback),所有参与者回滚本地事务
- 优点:严格遵守ACID原则
缺点:
- 性能较低:需要多次网络通信。
- 单点故障风险:事务管理器故障可能导致事务悬挂。
- 可能导致锁资源长时间持有:在阶段 1 等待结果时,资源被锁定
- 适用场景:需要强一致性且系统规模较小。
- 三阶段提交(3PC, Three-Phase Commit)
- 改进:在两段式提交的基础上引入一个预提交,降低阻塞风险
A. canCommit
(1) 事务管理器询问所有参与者是否能执行事务(类似投票)
(2) 如果所有参与者反馈“OK”,进入下一阶段;否则直接中止
B. 预提交(PreCommit)
(1)事务管理器向参与者发送预提交请求,参与者执行操作但未提交,同时记录状态
(2)事务管理器记录日志以备恢复
C. 提交(DoCommit)
(1) 如果预提交成功,则执行最终提交;否则回滚。
- 优点:比 2PC 更容错,减少锁资源时间。
- 缺点:仍有较高的性能开销,复杂度增加。
- 本地事务 + 补偿机制(TCC)
- 原理:将每个操作拆分为三个步骤
A.Try阶段
尝试执行,预留资源
B.Confirm阶段
确认执行,真正提交资源
C.Cancel阶段
取消执行,释放资源
流程:
- 所有服务先执行 Try 阶段,尝试完成本地资源准备
- 如果所有 Try 成功,则执行 Confirm 提交操作;否则执行 Cancel 回滚操作。
优点:
- 避免长时间占用锁。
- 开发者可根据业务场景定制操作逻辑。
缺点:
- 实现复杂:每个服务需要实现 Try、Confirm、Cancel
- 幂等性要求:所有操作必须幂等,确保重复调用不会出错
- 适用场景:业务逻辑允许补偿的场景,比如支付、订单管理等。
- 基于消息的最终一致性
- 原理:通过消息队列协调事务,保证系统最终达到一致性。
流程:
- 发起服务执行本地事务并将操作消息发送到消息队列(消息与本地事务保证原子性,如事务消息)。
- 消息队列将消息发送到相关服务。
- 消费者服务接收消息并完成本地操作,更新状态。
- 如果操作失败,可重试消息消费,确保最终一致性。
优点:
- 性能较好:避免分布式锁。
- 容错性强:消息队列支持重试机制。
缺点:
- 数据可能会暂时不一致。
- 依赖可靠的消息队列服务。
- 适用场景:允许一定程度的最终一致性,业务时延要求不高的场景,比如电商订单创建与库存扣减。
- 分布式事务协调器(框架支持)
- 现有分布式事务框架可以简化开发,例如:
(1)Seata:支持 TCC、AT(自动提交补偿)、SAGA 模式。
(2)Spring Cloud Transaction:提供基于消息的事务管理。
(3)Dubbo 分布式事务:支持高效的分布式事务管理。
优点:
- 降低开发复杂度。
- 提供多种分布式事务模型。
- 本地消息表
- 本地消息表本质是一个“可靠的中间站”,用来记录待发送的消息并确保它们最终能被消费。
- 核心思路是利用本地事务确保主业务和消息记录的一致性,通过异步发送机制达到最终一致性
- 适用于对数据最终一致性有要求的分布式场景,尤其是在微服务架构下,如订单管理、支付通知、库存扣减等系统。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。