分布式事务

基础理论

一个经典例子
拿转账作为例子,A需要转100元给B,那么需要给A的余额-100元,给B的余额+100元,整个转
要保证,A-100和B+100同时成功,或者同时失败。

本地事务

利用关系型数据库,把多条数据库语句作为一个整体进行操作的功能,被称为本地数据库事务。数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。
事务具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。
当业务系统不复杂时,可以在一个数据库、一个服务内对数据进行修改,完成转账,利用数据库事务,就可以保证转账业务的正确完成。

分布式事务

概念:分布式事务就是指事务的发起者、资源及资源管理器和事务协调者分别位于分布式系统的不同节点之上。
跨行转账:
银行跨行转账业务是一个典型分布式事务场景,假设A需要跨行转账给B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的ACID,只能够通过分布式事务来解决。
在上述转账的业务中,用户A-100操作和用户B+100操作不是位于同一个节点上。本质上来说,分布式事务就是为了保证在分布式场景下,数据操作的正确执行。
分布式事务在分布式环境下,为了满足可用性、性能与降级服务的需要,降低一致性与隔离性的要求,一方面遵循 BASE 理论:
  • 基本业务可用性(Basic Availability)
    • 响应时间上的损失:正常情况下的搜索引擎0.5秒即返回给用户结果,而基本可用看的搜索结果可能要1秒,2秒甚至3秒(超过3秒用户就接受不了了)
    • 功能上的损失:返回降级数据
  • 柔性状态(Soft state)
      • 原子性(硬状态) -> 要求多个节点的数据副本都是一致的,这是一种"硬状态"
      • 软状态(弱状态) -> 允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,
      允许系统在多个不同节点的数据副本存在数据延迟
  • 最终一致性(Eventual consistency)
    • 允许软状态在一定时间内存在,过了这个时间范围,各节点数据达到了最终一致
同样的,分布式事务也部分遵循 ACID 规范:
  • 原子性:严格遵循
  • 一致性:事务完成后的一致性严格遵循;事务中的一致性可适当放宽
  • 隔离性:并行事务间不可影响;事务中间结果可见性允许安全放宽
  • 持久性:严格遵循

分布式事务的解决方案

由于分布式事务方案,无法做到完全的ACID的保证,没有一种完美的方案,能够解决掉所有业务问题,因此在实际应用中,会根据业务场景,选择最适合的分布式事务方案。
三个角色:
全局事务管理器(TM,Transaction Manager)
资源管理器(RM,Resource Manager)
应用程序(AP,ApplicationProgram)

基于X/A协议

XA是由X/Open组织提出的分布式事务的规范,XA规范主要定义了(全局)事务管理器(TM)和(局部)资源管理器(RM)之间的接口。目前主流的数据库基本都支持XA事务,包括mysql、oracle、sqlserver、postgre。本地的数据库如mysql在XA中扮演的是RM角色。

两阶段提交2PC(Two-Phase Commit)

  • 第一阶段(prepare):即所有的参与者RM准备执行事务并锁住需要的资源。参与者ready时,向TM报告已准备就绪:
      • 询问 协调者向所有参与者发送事务请求,询问是否可执行事务操作,然后等待各个参与者的响应
      • 执行 各个参与者接收到协调者事务请求后,执行事务操作并将 Undo 和 Redo 信息记录事务日志中,不提交
      • 响应 如果参与者成功执行了事务并写入 Undo 和 Redo 信息,则向协调者返回 YES 响应,否则返回 NO 响应。当然,参与者也可能宕机,从而不会返回响应。
     
  • 第二阶段(commit/rollback):当事务管理者(TM)确认所有参与者(RM)都ready后,向所有参与者发送commit命令:
      • 正常提交
        • commit 请求 协调者向所有参与者发送 Commit 请求。
        • 事务提交 参与者收到 Commit 请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。
        • 反馈结果 参与者执行事务提交后向协调者发送 Ack 响应。
        • 完成事务 接收到所有参与者的 Ack 响应后,完成事务提交。
     
    • 回退
          在执行 Prepare 步骤过程中,如果某些参与者执行事务失败、宕机或与协调者之间的网络中断,那么协调者就无法收到所有参与者的 YES 响应,或者某个参与者返回了 No 响应,此时,协调者就会进入回退流程,对事务进行回退
        • rollback 请求 协调者向所有参与者发送 Rollback 请求。
        • 事务回滚 参与者收到 Rollback 后,使用 Prepare 阶段的 Undo 日志执行事务回滚,完成后释放事务执行期占用的所有资源。
        • 反馈结果 参与者执行事务回滚后向协调者发送 Ack 响应。
        • 中断事务 接收到所有参与者的 Ack 响应后,完成事务中断
       
二阶段提交缺点:
  1. 执行过程中,所有参与节点都是事务阻塞型的。参与者在等待协调者的指令时,其实是在等待其他参与者的响应。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态,比如数据库事务使用锁实现隔离性,事务没有提交,就会一直占用锁资源,导致并发量很低,性能很差。
  2. 参与者发生故障:协调者需要给每个参与者额外指定超时机制,超时后整个事务失败。
  3. 协调者发生故障:参与者会一直阻塞,选举新的协调者也无法知道上一个事务的全部状态信息(例如已等待 Prepare 响应的时长等),所以也无法顺利处理上一个事务。
  4. 数据不一致:TM或RM宕机或通信异常时,有的RM执行了commit,有的执行了rollback
  5. 协调者在发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。
先提交本地,最后提交整个事务
 

三阶段提交3PC(Three-Phase Commit)

与两阶段提交不同的是,三阶段提交有两个改动点。
  • 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的,在CanCommit阶段中可以尽早给出事务是否可以执行的判断,占用资源很少,提高了吞吐量。
  • 引入超时机制。同时在协调者和参与者中都引入超时机制。
1. CanCommit阶段
先问问能不能执行,区别于2阶段提交的先执行
2. PreCommit阶段
能执行的话再执行,执行本地操作,并将 Undo 和 Redo 信息记录事务日志中,如果参与者成功执行了事务并写入 Undo 和 Redo 信息,那么反馈 Ack 给协调者,并等待下一步指令
3. doCommit阶段
类似于2PC
 
改进:
降低了阻塞
  • 参与者返回 CanCommit 请求的响应后,等待第二阶段指令,若等待超时,则自动 abort,降低了阻塞;
  • 参与者返回 PreCommit 请求的响应后,等待第三阶段指令,若等待超时,则自动 commit 事务,也降低了阻塞;
解决单点故障问题
  • 参与者返回 CanCommit 请求的响应后,等待第二阶段指令,若协调者宕机,等待超时后自动 abort;
  • 参与者返回 PreCommit 请求的响应后,等待第三阶段指令,若协调者宕机,等待超时后自动 commit 事务;
 
数据不一致问题仍然是存在的,比如第三阶段协调者发出了 abort 请求,然后有些参与者没有收到 abort,那么就会自动 commit,造成数据不一致。
 

TCC(Try-Confirm-Cancel)

关于 TCC(Try-Confirm-Cancel)的概念,最早是由 Pat Helland 于 2007 年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。
TCC分为3个阶段
  • Try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
  • Confirm 阶段:确认执行真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源,Confirm 操作要求具备幂等设计,Confirm 失败后需要进行重试。
  • Cancel 阶段:取消执行,释放 Try 阶段预留的业务资源。Cancel 阶段的异常和 Confirm 阶段异常处理方案基本上一致,要求满足幂等设计。
TCC的Confirm/Cancel阶段在业务逻辑上是不允许返回失败的,如果因为网络或者其他临时故障,导致不能返回成功,TM会不断的重试,直到Confirm/Cancel返回成功
在TCC事务模型中,Confirm/Cancel业务可能会被重复调用,其原因很多。比如,全局事务在提交/回滚时会调用各TCC服务的Confirm/Cancel业务逻辑。执行这些Confirm/Cancel业务时,可能会出现如网络中断的故障而使得全局事务不能完成。因此,故障恢复机制后续仍然会重新提交/回滚这些未完成的全局事务,这样就会再次调用参与该全局事务的各TCC服务的Confirm/Cancel业务逻辑。
TCC特点如下:
  • 并发度较高,无长期资源锁定。
  • 开发量较大,需要提供Try/Confirm/Cancel接口。
  • TCC适用于订单类业务,对中间状态有约束的业务

本地消息表

//todo

事务消息

//todo
 

异常处理

空回滚:
在没有调用 TCC 资源 Try 方法的情况下,调用了二阶段的 Cancel 方法,Cancel 方法需要识别出这是一个空回滚,然后直接返回成功。
出现原因是当一个分支事务所在服务宕机或网络异常,分支事务调用记录为失败,这个时候其实是没有执行Try阶段,当故障恢复后,分布式事务进行回滚则会调用二阶段的Cancel方法,从而形成空回滚。
幂等:
由于任何一个请求都可能出现网络异常,出现重复请求,所以所有的分布式事务分支,都需要保证幂等性
悬挂:
悬挂就是对于一个分布式事务,其二阶段 Cancel 接口比 Try 接口先执行。
出现原因是在 RPC 调用分支事务try时,先注册分支事务,再执行RPC调用,如果此时 RPC 调用的网络发生拥堵,RPC 超时以后,TM就会通知RM回滚该分布式事务,可能回滚完成后,Try 的 RPC 请求才到达参与者真正执行。
 
异常解决方案//todo
posted @   bigCousinXu  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示