承接上文分布式事务Seata-AT模式
XA规范是什么?
- 是分布式事务处理DTP(Distributed Transaction Processing)的标准。
- 是描述全局的事务管理器和局部的资源管理器之间的接口规范。
- 允许多个资源(如数据库、应用服务、消息队列)在同一个事务中访问,使ACID属性跨应用程序而保持有序。
- 本质上可以理解为2PC,使用了2PC协议来保证所有的资源同时提交或回滚特定事务。
- 数据库本身支持本地事务ACID,XA让ACID库外应用。
DTP模式定义的几个角色?
- AP 应用程序
- RM 资源管理器,事务的参与者,具体的一个一个的微服务对应的数据源。
- TM 事务管理器,管理整个事务生命周期并协调各个RM。
- AP应用程序,比如订单服务、库存服务。
- RM资源管理器,可以理解为一个数据库mysql,应用程序通过JDBC连接,AP通过RM对资源进行控制,资源必须实现XA定义的接口。
- TM事务管理器,负责分配事务唯一标识,监控事务执行进度,并负责事务的提交或回滚。
TM一般是内嵌到应用程序当中,比如AP持有订单库和商品库2个数据源,应用程序通过TM通知订单库和商品库来创建订单和扣减库存,具体的2个RM此时是未提交事务,把数据锁住了,还没有提交,所以此时的商品和订单资源是锁定状态。
实际上RM代理了之前的数据库提交操作,RM告诉TM我准备好了。
2个RM都发送给TM说我准备好了,TM收到了所有的RM的通知,TM才发送下一个指令,通知所有RM进行真正的提交,然后释放资源,即2个RM分别把锁释放掉。
其实这个模式就是2PC,AT模式有一个记录日志的undolog,记录着之前的数据,XA模式没有undolog。
XA模式的核心
如果一个参与全局事务的RM资源失联了,收不到分支事务的结束命令,那它锁定的数据就会被一直锁定,就有可能会产生死锁,这是XA协议要解决的核心问题,也是Seata引入XA模式要解决的问题。
XA规范的本质就是2PC,利用数据库本身的CRUD来进行代理。
Seata事务模式的原型
DTP模式包含AP、RM、TM。
Seata XA模式包含TC事务协调者,TM事务管理器,RM资源管理器,TC是Seata自己定义的。
Seata定义了全局的事务框架,全局事务可以定义为若干个分支事务的整体协调。
TM开启全局事务,负责全局的提交或回滚请求给TC,TM会创建全局事务的xid。
TM如何把分支的事务定义在一个全局事务中的?
给整个全局事务中具体的分支事务规定一个统一的id,比如当前这个RM事务参与者的xid为1,另外一个RM的xid也为1,就代表这2个RM在一个全局事务上。
TM创建一个xid规定哪些分支事务属于当前这个全局事务。
TM向TC发起提交或回滚全局事务的请求,把全局事务id绑定在分支事务上,代表在一个全局事务中。
具体的RM需要向TC进行注册,告诉TC我当前的执行情况,成功了还是失败了,再由TC告诉RM是提交还是回滚,这是整个的Seata XA事务模式。
Seata XA事务模式也是2PC模式,
- 执行阶段:执行分支事务并保证执行结果且满足可回滚和可持久化
- 完成阶段:TM根据执行阶段的结果形成决议,应用通过TM发起全局提交或回滚请求给TC,TC命令RM驱动分支事务进行提交或回滚。
回顾AT事务模式
AT模式是2PC的变种,TM进行全局事务提交和回滚,TM给具体的分支事务加xid,告诉当前分支事务属于这一个全局事务,这部分AT和XA都是一样的。
AT模式解析sql语句,所以在第一阶段(执行阶段),解析当前sql的结果并且记录undolog日志。
首先RM分支事务进行注册到TC中,告诉TC当前分支事务的执行结果是yes还是no。
最终由TC告诉分支事务,谁失败就需要回滚,回滚的时候用到了undolog,根据undolog记录的修改之前的数据来进行反向的补偿更新,这是第二阶段。如果都是yes,就进行整体的提交。TM负责全局的事务开启和提交、回滚操作,TC告诉具体的分支事务是提交还是回滚。
1、执行阶段
- 可回滚:根据sql解析结果,记录回滚日志undolog
- 持久化:把日志记录到数据库中
2、完成阶段
- 提交的时候异步删除回滚日志
- 回滚的时候,根据回滚日志反向补偿
Seata XA模式
Seata XA模式就是把XA协议归纳到Seata中,在Seata定义的分布式事务架构内,利用数据库、消息服务等对XA的支持,以XA协议的机制来管理分布式事务的一种机制。
Seata XA、AT、 SAGA、TCC都是遵循整个Seata事务模式来进行的。
XA模式开启,执行sql,XA模式结束,这是XA的准备阶段,第二阶段是XA进行提交或回滚。
在Seata的XA模式与AT的区别是XA没有undolog。
AT记录了undolog,根据undolog反向补偿,达到最终一致性。
XA是强一致性,通过数据库的ACID执行的,没有中间状态。
最终一致性存在中间状态,XA不存在中间状态,XA是强一致性的。
第一阶段是执行阶段,保证可回滚和持久化,XA模式对sql进行解析后告诉TC每个分支事务当前执行的情况,TC来决定是提交还是回滚。
把AT替换成了XA,整个的Seata的分布式事务框架不变,只不过AT变成了强一致性的XA。
可回滚是指在XA分支中进行业务sql的执行,由数据库资源对XA协议支持来保证可回滚,即依赖数据源自带的事务的ACID来进行回滚。
持久化是指XA分支在执行完成以后,即XA start和end完成之后,由数据库资源进行持久化,可以保证任何意外都不会造成无法回滚的情况,这样就解决了XA协议的核心痛点。
mysql和oracle都支持XA协议,都支持本地事务,可以保证在任何情况下数据的持久性。
XA的价值
Seata已经支持了3大事务模式AT、SAGA、TCC,为什么还要支持XA?
这3个都是补偿型的,存在中间状态。
构建在事务资源之上的模型,要么在中间件层面实现,要么在应用层面实现,事务资源本身对分布式事务是无感知的。
所谓的事务资源是本地事务,本地事务对分支事务是无法感知的,无法做到真正的全局一致性,即存在中间状态。
比如一个库存当前是100,扣50,还剩50,仓库管理员连接数据库查看当前结果,读到的是50,由于当前这个事务出现了问题,回滚了,50回滚到100了。
仓库管理员读到的是50,就产生了脏读,所谓的脏数据是中间状态,管理员再次连接数据库可以拿到回滚之后的数据。数据50是中间的状态,100是最终一致性的状态。
AT模式:订单下单之后,100个库存扣减1还剩99,订单创建失败了,需要整个全局回滚,undolog中会记录之前的值100 ,但是在事务执行的过程中,会存在99的状态。如果库存减1了,订单并没有真正创建,这个时候读库存,读到的确实是99,这个99就是所谓的中间状态,这个就是脏读。
AT、SAGA、TCC都是补偿型的,都会出现脏读的情况,当然Seata本身是有预防的,但确实会存在这些问题:可能会得到脏数据且最终一致性是允许有中间状态的,这也解释了为什么Seata支持XA,因为XA是强一致性的。
XA没有undolog日志,也不会暴露中间状态。
与补偿型不同,事务资源本身提供对XA规范和协议的支持,事务资源感知并参与分布式事务处理的过程。
数据资源(数据库) 可以保证从任意视角对数据库访问可以有效的隔离且满足全局事务的一致性。
补偿型的事务模型会出现中间状态,当想做到强一致性的时候就需要XA。
XA由数据库本身保证,不会出现仓库管理员查询看到中间状态的情况,这是由本地事务隔离性保证的。
除了强一致性这个优点,还有无业务侵入、数据库支持广泛、多语言的支持、不涉及到sql解析、XA模式对Seata的RM要求比较少、传统的XA模式应用可以平滑迁移到Seata平台的优点。
一致性、可靠性、易用性、性能等系统设计约束需要不同的事务处理机制去完成,Seata提供了全面解决分布式事务问题的标准化平台。
无业务侵入的有AT和XA,有业务侵入的有TCC、 SAGA,XA模式的加入补全了Seata在全局一致性下的缺口。