彻底掌握分布式事务2PC、3PC模型(二)
DTP 模型和 XA 规范
X/Open 组织定义了分布式事务的模型(DTP)和 分布式事务协议(XA),DTP 由以下几个模型元素组成
- AP(Application 应用程序):用于定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作
- TM(Transaction Manager 事务管理器):负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等
- RM(Resource Manager 资源管理器):如数据库、文件系统等,并提供访问资源的方式
- CRM(Communication Resource Manager 通信资源管理器):控制一个TM域(TM domain)内或者跨TM域的分布式应用之间的通信
- CP(Communication Protocol 通信协议):提供CRM提供的分布式应用节点之间的底层通信服务
在 DTP 分布式事务模型中,基本组成需要涵盖 AP、TM、RMS(不需要 CRM、CP 也是可以的),如下图所示
XA 规范
XA 规范最重要的作用就是定义 RM(资源管理器)与 TM(事务管理器)之间的交互接口。另外,XA 规范除了定义 2PC 之间的交互接口外,同时对 2PC 进行了优化
梳理下 DTP、XA、2PC 之间的关系
DTP 规定了分布式事务中的角色模型,并在其中指定了全局事务的控制需要使用 2PC 协议来保证数据的一致性
2PC 是 Two-Phase Commit 的缩写,即二阶段提交,是计算机网络尤其是数据库领域内,为了保证分布式系统架构下所有节点在进行事务处理过程中能够保证原子性和一致性而设计的一种算法。同时,2PC 也被认为是一种一致性协议,用来保证分布式系统数据的一致性
XA 规范是 X/Open 组织提出的分布式事务处理规范,XA 规范定义了 2PC(两阶段提交协议)中需要用到的接口,也就是上图中 RM 和 TM 之间的交互。2PC 和 XA 两者最容易混淆,可以这么理解,DTP 模型定义 TM 和 RM 之间通讯的接口规范叫 XA,然后 关系数据库(比如MySQL)基于 X/Open 提出的的 XA 规范(核心依赖于 2PC 算法)被称为 XA 方案
2PC 一致性算法
当应用程序(AP)发起一个事务操作需要跨越多个分布式节点的时候,每一个分布式节点(RM)知道自己进行事务操作的结果是成功或是失败,但是却不能获取到其它分布式节点的操作结果。为了保证事务处理的 ACID 特性,就需要引入称为"协调者"的组件(TM)来进行统一调度分布式的执行逻辑
协调者负责调度参与整体事务的分布式节点的行为,并最终决定这些分布式节点要把事务进行提交还是回滚。所以,基于这种思想下,衍生出了二阶段提交和三阶段提交两种分布式一致性算法协议。二阶段指的是准备阶段和提交阶段,下面我们先看准备阶段都做了什么事情
2PC-准备阶段
二阶段提交中第一阶段也叫做"投票阶段",即各参与者投票表明自身是否继续执行接下来的事务提交步骤
- 事务询问:协调者向所有参与本次分布式事务的参与者发送事务内容,询问是否可以执行事务提交操作,然后开始等待各个参与者的响应
- 执行事务:参与者收到协调者的事务请求,执行对应的事务,并将内容写入 Undo 和 Redo 日志
- 返回响应:如果各个参与者执行了事务,那么反馈协调者 Yes 响应;如果各个参与者没有能够成功执行事务,那么就会返回协调者 No 响应
如果第一阶段全部参与者返回成功响应,那么进入事务提交步骤,反之本次分布式事务以失败返回。以 MySQL 数据库为例,在第一阶段,事务管理器(TM)向所有涉及到的数据库(RM)发出 prepare(准备提交) 请求,数据库收到请求后执行数据修改和日志记录处理,处理完成后把事务的状态修改为 "可提交",最终将结果返回给事务处理器
2PC-提交阶段
提交阶段分为两个流程,一个是各参与者正常执行事务提交流程,并返回 Yes 响应,表示各参与者投票执行成功;一个是各参与者当中有执行失败返回 No 响应或超时情况,将触发全局回滚,表示分布式事务执行失败
- 执行事务提交
- 中断事务
执行事务提交
假设协调者从所有的参与者获得的反馈都是 Yes 响应,那么就会执行事务提交操作
- 事务提交:协调者向所有参与者节点发出 Commit 请求,各个参与者接收到 Commit 请求后,将本地事务进行提交操作,并在完成提交之后释放事务执行周期内占用的事务资源
- 完成事务:各个参与者完成事务提交之后,向协调者发送 Ack 响应,协调者接收到响应后完成本次分布式事务
中断事务
假设任意一个事务参与者节点向协调者反馈了 No 响应(注意这里的 No 响应指的是第一阶段),或者在等待超时之后,协调者没有接到所有参与者的反馈响应,那么就会进行事务中断流程 - 事务回滚:协调者向所有参与者发出 Rollback 请求,参与者接收到回滚请求后,使用第一阶段写入的 undo log 执行事务的回滚,并在完成回滚事务之后释放占用的资源
- 中断事务:参与者在完成事务回滚之后,向协调者发送 Ack 消息,协调者接收到事务参与者的 Ack 消息之后,完成事务中断
2PC 优缺点
2PC 提交将事务的处理过程分为了投票和执行两个阶段,核心思想就是对每个事务都采用先尝试后提交的方式处理。2PC 优点显而易见,那就是 原理简单,实现方便。简单也意味着很多地方不能尽善尽美,这里梳理三个比较核心的缺陷
- 同步阻塞:无论是在第一阶段的过程中,还是在第二阶段,所有的参与者资源和协调者资源都是被锁住的,只有当所有节点准备完毕,事务协调者才会通知进行全局提交,参与者进行本地事务提交后才会释放资源。这样的过程会比较漫长,对性能影响比较大
- 单点故障:如果协调者出现问题,那么整个二阶段提交流程将无法运转。另外,如果协调者是在第二阶段出现了故障,那么其它参与者将会处于锁定事务资源的状态中
- 数据不一致性:当协调者在第二阶段向所有参与者发送 Commit 请求后,发生了局部网络异常或者协调者在尚未发送完 Commit 请求之前自身发生了崩溃,导致只有部分参与者接收到 Commit 请求,那么接收到的参与者就会进行提交事务,进而形成了数据不一致性
由于 2PC 的简单方便,所以会产生上述的同步阻塞、单点故障、数据不一致等情况,所以在 2PC 的基础上做了改进,推行出了三阶段提交(3PC)
使用 2PC 存在诸多限制,首先就是数据库需要支持 XA 规范,而且性能与数据一致性数据均不友好,所以 Seata 中虽然支持 XA 模式,但是主推的还是 AT 模式
文章转自公众号:龙台的技术笔记