
两阶段提交又称2PC,2PC是一个非常经典的强一致、中心化的原子提交协议。这里所说的中心化是指协议中有两类节点:一个是中心化协调者节点和 N个参与者节点 。
两个阶段:
第一阶段:投票阶段 。
第二阶段:提交/执行阶段。
生活中的2PC
A组织B、C和D三个人去爬山:如果所有人都同意去爬山,那么活动将举行;如果有一人不同意去爬山,那么活动将取消。

首先A将成为该活动的协调者,B、C和D将成为该活动的参与者。

具体流程:
阶段1:
① A发邮件给B、C和D,提出下周三去爬山,问是否同意。那么此时A需要等待B、C和D的邮件。
② B、C和D分别查看自己的日程安排表。B、C发现自己在当日没有活动安排,则发邮件告诉A它们同意下周三去爬山。由于某种原因, D白天没有查看邮 件。那么此时A、B和C均需要等待。到晚上的时候,D发现了A的邮件,然后查看日程安排,发现周三当天已经有别的安排,那么D回复A说活动取吧。
阶段2:
① 此时A收到了所有活动参与者的邮件,并且A发现D下周三不能去爬山。那么A将发邮件通知B、C和D,下周三爬山活动取消。
② 此时B、C回复A“太可惜了”,D回复A“不好意思”。至此该事务终止。
2PC阶段处理流程
举例订单服务A,需要调用支付服务B去支付,支付成功则处理购物订单为待发货状态,否则就需要将购物订单处理为失败状态。
第一阶段:投票阶段

第一阶段分三步:
⭐ **事物询问:**协调者 向所有的 参与者 发送事务预处理请求,称之为Prepare,并开始等待各参与者的响应。
⭐ **执行本地事物:**各个 参与者节点执行本地事务操作,但在执行完成后并不会真正提交数据库本地事务,而是先向协调者报告说:“我这边可以处理了/我这边不能处理”。.
⭐ **各个参与者向协调者反馈事物询问的响应:**如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行,如果没有参与者成功执行事务,那么就反馈给协调者No响应,表示事务不可以执行。第一阶段执行完后,会有两种可能。1、所有都返回Yes. 2、有一个或者多个返回No。
第二阶段:提交/执行阶段(成功流程)
**成功条件 :**所有参与者都返回Yes。

异常流程第二阶段也分为两步
⭐ 发送回滚请求
协调者 向所有参与者节点发出 RoollBack 请求.
⭐ 事务回滚
参与者 接收到RoollBack请求后,会回滚本地事务。
2PC缺点
⭐ 性能问题
无论是在第一阶段的过程中,还是在第二阶段,所有的参与者资源和协调者资源都是被锁住的,只有当所有节点准备完毕,事务协调者才会通知进行全局提交,参与者进行本地事务提交后才会释放资源。这样的过程会比较漫长,对性能影响比较大。
⭐ 单节点故障
由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。

什么是DTP
2PC的传统方案是在数据库层面实现的,如Oracle、MySQL都支持2PC协议,为了统一标准减少行业内不必要的对接成本,需要制定标准化的处理模型及接口标准,国际开放标准组织Open Group定义分布式事务处理模型DTP(Distributed Transaction Processing Reference Model)。
DTP模型定义角色
⭐ AP(Application Program):即应用程序,可以理解为使用DTP分布式事务的程序。
⭐ RM(Resource Manager):即资源管理器,可以理解为事务的参与者,一般情况下是指一个数据库实例,通过资源管理器对该数据库进行控制,资源管理器控制着分支事务。
⭐ TM(Transaction Manager):事务管理器,负责协调和管理事务,事务管理器控制着全局事务,管理事务生命周期,并协调各个RM。全局事务是指分布式事务处理环境中,需要操作多个数据库共同完成一个工作,这个工作即是一个全局事务。
注意:
DTP模型定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA协议来实现2PC又称为XA方案。

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

Seata是什么
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 为用户提供了 AT、TCC、SAGA和 XA 事务模式,为用户打造一站式的分布式解决方案。

Seata整体框架
全局事务与分支事务的关系图

与传统2PC的模型类似,Seata定义了三个组件来协议分布式事务的处理过程

具体流程:
⭐ Transaction Coordinator(TC):事务协调器,它是独立的中间件,需要独立部署运行,它维护全局事务的运行状态,接收TM指令发起全局事务的提交与回滚,负责与RM通信协调各个分支事务的提交或回滚。
⭐ Transaction Manager(TM):事务管理器,TM需要嵌入应用程序中工作,它负责开启一个全局事务,并最终向TC发起全局提交或全局回滚的指令。
⭐ Resource Manager(RM):控制分支事务,负责分支注册、状态汇报,并接收事务协调器TC的指令,驱动分支(本地)事务的提交和回滚。
还拿新用户注册送积分举例Seata的分布式事务过程

执行流程 :
⭐ 用户服务的TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID。
⭐ 用户服务的RM向TC注册分支事务,该分支事务在用户服务执行新增用户逻辑,并将其纳入XID对应全局事务的管辖。
⭐ 用户服务执行分支事务,向用户表插入一条记录。
⭐ 逻辑执行到远程调用积分服务时(XID在微服务调用链路的上下文中传播)。积分服务的RM向TC注册分支事务,该分支事务执行增加积分的逻辑,并将其纳入XID对应全局事务的管辖。
⭐ 积分服务执行分支事务,向积分记录表插入一条记录,执行完毕后,返回用户服务。
⭐ 用户服务分支事务执行完毕。
⭐ TM向TC发起针对XID的全局提交或回滚决议。
⭐ TC调度XID下管辖的全部分支事务完成提交或回滚请求。
Seata实现2PC与传统2PC的差别
⭐ 架构层次方面,传统2PC方案的RM实际上是在数据库层,RM本质上就是数据库自身,通过XA协议实现,而Seata的RM是以jar包的形式作为中间件层部署在应用程序的这一侧的。
⭐ 性能层面:两阶段提交方面,传统2PC无论第二阶段的决议是commit还是rollbcak,事务性资源的锁都要保持到Phase2完成才释放。而Seata的做法是在Phase1就将本地事务提交,这样就可以省去Phase2持锁的时间,整体提高效率。