跳到主要内容

03、分布式事务 实战 - 分布式事务解决方法-2PC(两阶段提交)

一 什么是2PC

2PC即两阶段提交协议,将整个全局事务分为准备阶段,提交阶段。

1、 准备阶段(PreparePhase):事务管理器给每个本地事务发送Prepare消息,每个本地事务执行本地事务,但不提交并且写本地的Undo/Redo日志并且继续持有锁资源;

Undo:记录数据库修改前的数据,用于回滚事务。

Redo:记录数据库修改后的数据,用户提交事务。

2、 提交阶段(CommitPhase):如果事务管理器收到某个本地事务执行失败的消息,直接给每个本地事务发送回滚消息(Rollback),否则,事务管理器给每个本地事务发送提交消息(Commit)每个本地事务根据事务管理器消息执行回滚或提交,并且释放锁资源;

成功图例

 

失败图例
 

二 2PC具体实现方案之XA方案

  2PC的传统方案是在数据库层面实现的,如Oracle、MySQL都支持2PC协议,为了统一标准减少行业内不必要的对接成本,需要制定标准化的处理模型及接口标准,国际开放标准组织Open Group定义了分布式事务处理模型 DTP(Distributed Transaction Processing Reference Model)。 

DTP模型定义几个角色:

  • RM(Resource Manager):资源管理器,可以理解为事务的参与者,控制着分支事务。
  • TM(Transaction Manager):事务管理器,控制全局事务,控制全局事务生命周期,协调各个RM。
  • AP(Application Program):应用程序,可以理解为使用DTP的程序。

XA协议就是RM与TM之间通讯的接口规范
XA方案就是基于数据库XA协议来实现2PC的方案,例如:JTA(Java Transaction Manager) : 是Java规范,是XA在Java上的实现。

流程举例,新用户注册送积分,用户库与积分库不是同一个库:

1、 应用程序(AP)持有用户库和积分库两个数据源;
2、 应用程序(AP)通过TM通知用户库RM新增用户,同时通知积分库RM为该用户新增积分,RM此时并未提交事务,此时用户和积分资源锁定;
3、 TM收到执行回复,只要有一方失败则分别向其他RM发起回滚事务,回滚完毕,资源锁释放;
4、 TM收到执行回复,全部成功,此时向所有RM发起提交事务,提交完毕,资源锁释放;

XA方案的缺点:

  • 需要数据库支持XA协议,不过大部分常用数据库都支持(MySql、Oracle)。
  • 资源锁持续了两个阶段,性能较差。

三 2PC具体实现方案之Seata方案

3.1 什么是Seata

Seata是阿里巴巴中间件团队发起的开源项目Fescar,后更名为Seata,是一款开源的分布式事务框架。
Seata作用于应用层通过对本地事务的协调完成全局事务。对业务0侵入来解决微服务下的分布式事务问题,目前提供AT模式(即2PC)和TCC模式的分布式事务解决方案。

3.2 Seata三大组件

Seata定义了三大组件来处理分布式事务:

  • 事务协调器(Transaction Coordinator):独立的中间件,需要独立部署。维持全局事务的状态,接受TM发起全局事务的提交与回滚,负责RM通信协调各分支事务的提交与回滚。
  • 事务管理器(Transaction Manager):需要嵌入应用程序中工作,负责向TC发起全局事务,并最终向TC发起全局提交或全局回滚。
  • 资源管理器(Resource Manager):控制分支事务,接受TC的指令,驱动分支事务的提交与回滚。

3.2 Seata工作流程

拿新用户注册送积分举例,用户库与积分库不是同一个库:

1、 用户服务的TM向TC申请开启一个全局事务,TC全局事务开启成功,并生成一个全局唯一XID返回给TM;
2、 用户服务RM带着XID向TC注册分支事务,TC将其纳入XID对应的全局事务,并返回BranchID;
3、 用户服务执行分支事务,向用户表插入数据,并向undo_log写入数据(用于回滚),并提交分支事务,然后向TC上报分支事务执行结果;
4、 用户服务带着XID调用积分服务;
5、 积分服务RM带着XID向TC注册分支事务,TC将其纳入XID对应的全局事务,并返回BranchID;
6、 积分服务执行分支事务,向积分表插入数据,并向undo_log写入数据(用于回滚),积分服务返回用户服务,并提交分支事务,然后向TC上报分支事务执行结果;
7、 用户服务TM向TC发起针对XID的全局提交或回滚;
8、 TC调度XID下的全部分支事务完成提交或回滚;

成功图例:
 

回滚图例:
 

3.3 Seata与传统2PC比较

  • RM区别:传统2PC的RM在数据库层,实际是数据库本身,通过XA协议实现。而Seata以Jar的形式作为中间件部署在应用层。
  • 分支事务提交时间:2PC在第二阶段,Seata在第一阶段。提高了性能。