分布式事务:XA和Seata的XA模式
上一篇内容《从2PC和容错共识算法讨论zookeeper中的Create请求》介绍了保证分布式事务提交的两阶段提交协议,而XA是针对两阶段提交提出的接口实现标准,本文则对XA进行介绍。
1. XA
XA (eXtended Architecture 扩展架构)是X/Open组织提出的跨异构技术实现两阶段提交的接口标准。
分布式事务包含两种类型:数据库内部的分布式事务,在这种情况下,所有参与事务的节点都运行相同的数据库软件;异构分布式事务,参与者由两种或两种以上的不同数据库软件组成。
它于 1991 年推出并得到了广泛的实现:许多传统关系数据库包括 PostgreSQL、MySQL、DB2、SQL Server 和 Oracle;消息代理包括 ActiveMQ、HornetQ、MSMQ 和 IBM MQ都支持 XA。它不是一个网络协议而是定义了事务管理器(Transaction Manager)、应用程序(Application Program)和资源管理器(Resource Manager)之间交互的CAPI(Common Application Programming Interface)接口标准,如下图所示,但是标准中并没有指明该如何实现,例如在Java EE中,XA使用的是Java事务API(JTA, Java Transaction API)实现的。
CAPI: 国际标准的通用应用交互接口。

其中三个组件的职责如下:
应用程序(Application Program):负责定义事务的开启、提交或中止,并能够访问事务内的资源(数据库等)
资源管理器(Resource Manager):负责对资源进行管理,相当于两阶段提交中的参与者,能够与事务管理器通过接口交互来传递必要的事务信息
事务管理器(Transaction Manager):负责管理全局事务,分配事务ID,监控事务的执行进度,并负责事务的开启、提交和回滚等,相当于两阶段提交中的协调者
XA同样也分为准备阶段和提交阶段,它对分布式事务管理的流程如下
准备阶段:AP与TM交互,开启一个全局分布式事务,并发送请求到每个RM,执行数据变更逻辑,此时每个RM会向TM发送请求注册分支事务,在执行完业务逻辑后报告准备提交的状态(事务执行完未提交),之后AP会根据RM的响应在提交阶段做出反馈
提交阶段:如果所有的RM都回复“是”,表示它们已经准备好提交,那么AP会在该阶段向TM发出提交请求,分布式事务提交;否则,AP会向TM发出中止请求,分布式事务回滚
2. Seata的XA的模式
Seata中有三个角色事务管理器(Transaction Manager)、资源管理器(Resource Manager)和事务协调者(Transaction Coordinator)。在XA模式下,利用事务资源(数据库、消息服务等)对XA协议的支持,来对分布式事务进行管理。
但是,在Seata中三个角色的定义与XA协议标准中角色的定义有所区别:事务管理器(Transaction Manager)应该对应XA协议中的应用程序(Application Program);事务协调者(Transaction Coordinator)对应XA协议中的事务管理器(Transaction Manager)。我认为它们只是在命名上的区别,为了上下文各名词的统一,避免发生因名词不一致而理解混淆的问题,决定以XA标准协议中的定义进行讲解,特此强调。
下图是Seata管理分布式事务的流程图,与第一小节中所述事务流程相同,不再赘述。

2.1 XA模式实战分析
有了理论基础,我们以商城系统为例进行简单地演示:订单、商品和购物车分别为三个微服务系统,在执行下单流程时会修改商品库存,生成订单和删除购物车中的商品,业务流程代码如下,注意其中包含事务异常回滚的代码
@GlobalTransactional
@Transactional(rollbackFor = Exception.class)
public void saveOrder(OrderSaveParam orderSaveParam) {
// 参数校验等必要操作
// ...
// 校验商品库存和上架状态
checkGoodsStatusAndStock(goodsList, goodsCountMap);
// 修改库存
reduceGoodsCount(goodsCountMap);
// 生成订单
saveOrder(goodsList, goodsCountMap, orderSaveParam.getAddressId());
// 删除购物车中商品
shoppingCartService.deleteShoppingCartItem(orderSaveParam.getCartItemIds(), SecurityConstants.INNER);
// 异常回滚事务
int i = 1 / 0;
}
分布式事务执行的准备阶段,流程图如下

Order Server 在创建订单之前,会向 Seata Server(TM) 注册全局事务,并分配事务ID,对应的控制台日志如下
2023-06-17 22:07:06.479 INFO 74703 --- [io-29009-exec-2] i.seata.tm.api.DefaultGlobalTransaction : Begin new global transaction [127.0.0.1:8091:36427221250506976]Order Server REST调用 Goods Server 扣减商品数量,Goods Server 在执行数据修改逻辑前会向 Seata Server 注册分支事务,执行完业务逻辑后,并不执行事务提交
Order Server REST调用 ShoppingCart Server 删除购物车中的商品,ShoppingCart Server 在执行数据修改逻辑前会向 Seata Server 注册分支事务,执行完业务逻辑后,同样不执行事务提交
Order Server 本地执行生成订单和其他逻辑
接下来是分布式事务执行的提交阶段,因生成订单中代码逻辑抛出异常,所以该分布式事务会回滚,OrderServer中对应日志如下
2023-06-17 22:07:07.029 INFO 74703 --- [io-29009-exec-2] i.s.rm.datasource.xa.ConnectionProxyXA : 127.0.0.1:8091:36427221250506976-36427221250506978 was rollbacked
2023-06-17 22:07:07.220 INFO 74703 --- [io-29009-exec-2] i.seata.tm.api.DefaultGlobalTransaction : Suspending current transaction, xid = 127.0.0.1:8091:36427221250506976
2023-06-17 22:07:07.220 INFO 74703 --- [io-29009-exec-2] i.seata.tm.api.DefaultGlobalTransaction : [127.0.0.1:8091:36427221250506976] rollback status: Rollbacked

Order Server 向 Seata Server 发送中止请求,随后 Seata Server 向 Goods Server 和 ShoppingCart Server 发送事务回滚请求
Goods Server 和 ShoppingCart Server 收到事务回滚请求后,将各自注册的分支事务回滚,最终全局分布式事务回滚,以保证数据的一致性。Goods Server 分支事务回滚对应的日志如下,可以发现分支事务的ID为全局事务ID-分支ID,并显示PhaseTwo_Rollbacked 在阶段二回滚
2023-06-17 22:07:07.081 INFO 74680 --- [h_RMROLE_1_4_24] i.s.c.r.p.c.RmBranchRollbackProcessor : rm handle branch rollback process:xid=127.0.0.1:8091:36427221250506976,branchId=36427221250506986,branchType=XA,resourceId=jdbc:mysql://127.0.0.1:3306/fy_mall_goods,applicationData=null
2023-06-17 22:07:07.081 INFO 74680 --- [h_RMROLE_1_4_24] io.seata.rm.AbstractRMHandler : Branch Rollbacking: 127.0.0.1:8091:36427221250506976 36427221250506986 jdbc:mysql://127.0.0.1:3306/fy_mall_goods
2023-06-17 22:07:07.096 INFO 74680 --- [h_RMROLE_1_4_24] i.s.rm.datasource.xa.ResourceManagerXA : 127.0.0.1:8091:36427221250506976-36427221250506986 was rollbacked
2023-06-17 22:07:07.096 INFO 74680 --- [h_RMROLE_1_4_24] io.seata.rm.AbstractRMHandler : Branch Rollbacked result: PhaseTwo_Rollbacked
注:如果有朋友想试试Seata的XA模式,可以参考示例代码仓库FangYuan33/book-spring-cloud,对应的方法入口为
/saveOrder
3. 对XA的思考
XA能够保持多个参与者数据相互一致,但是同时也引入了比较严重的运维问题。
因为如果协调者宕机,那么其中已经准备但未提交事务的所有参与者都会被阻塞。被阻塞的根本是锁,例如在读已提交隔离级别上,数据库事务通常会获取到待修改行数据的行级排他锁来防止脏写。在分布式事务提交或中止前,参与者数据库不能释放这些锁,因此协调者宕机多久,这些锁就要持有多久(在没有认为干预的情况下)。这些锁被持有的期间,导致其他事务不能修改这些数据(根据数据库的不同,读取操作也可能被阻塞),所以这些数据相关的业务都会被阻塞,导致应用大面积的不可用,直至存疑事务被解决(提交/中止)。
理论上,如果协调者崩溃并重新启动,它应该从日志中恢复事务的状态,并解决现存的疑虑事务,但是在实际生产中,仍然会有疑虑事务的出现(可能是事务日志被破坏)。也许你可能会考虑将相关应用的数据库服务器重启,但是在2PC正确的实现中,为了原子性的保证,重启后也必须持有存疑事务的锁。那么这样唯一的解决方案是让管理员手动提交还是回滚事务,这是引入运维问题的所在。不过,许多XA事务的实现都有一个叫做启发式决策的逃生出口,允许参与者单方面决定提交或放弃一个存疑事务,而无需等待协调者的决定,但是这也正是避免灾难性情况的手段,而不是为了日常的使用,因为这种方式有可能会破坏事务的原子性。
所以,协调者的高可用是需要我们考虑的问题,它本身也是一种数据库(保存了事务的结果),需要像其他应用数据库服务一样被认真的对待。
巨人的肩膀
《数据密集型应用系统设计》:第九章 一致性与共识
原文收录:GitHub-Enthusiasm
作者:京东物流 王奕龙
来源:京东云开发者社区 自猿其说Tech 转载请注明来源
分布式事务:XA和Seata的XA模式的更多相关文章
- 分布式事务之解决方案(XA和2PC)
3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案有2PC.TCC.可靠消息最终一致性.最大努力通知这几种. 3.1. 什么是2PC 2PC即两阶段提交协议,是将整 ...
- [转帖]分布式事务之解决方案(XA和2PC)
分布式事务之解决方案(XA和2PC) https://zhuanlan.zhihu.com/p/93459200 3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案 ...
- 【转帖】分布式事务之解决方案(XA和2PC)
分布式事务之解决方案(XA和2PC) https://zhuanlan.zhihu.com/p/93459200 博彦信息技术有限公司 java工程师 3. 分布式事务解决方案之2PC(两阶段提交 ...
- 微服务痛点-基于Dubbo + Seata的分布式事务(AT)模式
前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...
- 微服务痛点-基于Dubbo + Seata的分布式事务(TCC模式)
前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...
- 微服务架构 | 11.1 整合 Seata AT 模式实现分布式事务
目录 前言 1. Seata 基础知识 1.1 Seata 的 AT 模式 1.2 Seata AT 模式的工作流程 1.3 Seata 服务端的存储模式 1.4 Seata 与 Spring Clo ...
- 分布式事务(Seata) 四大模式详解
前言 在上一节中我们讲解了,关于分布式事务和seata的基本介绍和使用,感兴趣的小伙伴可以回顾一下<别再说你不知道分布式事务了!> 最后小农也说了,下期会带给大家关于Seata中关于sea ...
- 如何实现XA式、非XA式Spring分布式事务
Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...
- 非XA式Spring分布式事务
Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...
- MySQL 中基于 XA 实现的分布式事务
1 XA协议 首先我们来简要看下分布式事务处理的XA规范可知XA规范中分布式事务有AP,RM,TM组成: 其中应用程序(Application Program ,简称AP):AP定义事务边界(定义事务 ...
随机推荐
- 前端Vue自定义导航栏菜单 定制左侧导航菜单按钮 中部logo图标 右侧导航菜单按钮
前端Vue自定义导航栏菜单 定制左侧导航菜单按钮 中部logo图标 右侧导航菜单按钮, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin? ...
- hashtable分析
1.什么是Hash表? Hash表又被称为散列表,是根据关键码值(key-value)也就是键值对来直接访问的一种数据结构.也就是说,它通过把关键码值映射到表中的一个位置来访问记录,用以加快查找的 ...
- C# Collections
1. Generic 1.1 List<T> No need to say this is the most commonly used data structure in C# coll ...
- 完全兼容DynamoDB协议!GaussDB(for Cassandra)为NoSQL注入新活力
摘要:DynamoDB是一款托管式的NoSQL数据库服务,支持多种数据模型,广泛应用于电商.社交媒体.游戏.IoT等场景. 本文分享自华为云社区<完全兼容DynamoDB协议!GaussDB(f ...
- 【Linq】 join 子句中其中一个表达式的类型不正确。在对“GroupJoin”的调用中,类型推理失败。
报错代码: 原因分析:on后面的两个关联条件 数据类型不匹配,调整为一致即可.
- 快速打开指定目录的cmd
待解决问题 在使用dirsearch.sqlmap等工具时需要进入对应的目录再打开cmd,现要实现配合utools快速打开对应目录的cmd 解决办法:创捷快捷方式 在对应的文件夹下创建一个快捷方式,对 ...
- axios详解以及完整封装方法
""" 一.axios是什么 Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中. 它是 isomorphic 的(即同一套代码可以运行 ...
- 【转载】Linux虚拟化KVM-Qemu分析(十)之virtio驱动
原文信息 作者:LoyenWang 出处:https://www.cnblogs.com/LoyenWang/ 公众号:LoyenWang 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者 ...
- Git 环境配置(详解版)
前言 Git下载官网:https://git-scm.com/downloads 本次使用Github为配置前提(Gitee步骤类似) 环境搭建 1.git安装好去GitHub上注册一个账号,注册好后 ...
- jquery解决跨域问题
在Ajax请求的url不是本地或者同一个服务器下面的URI,最后虽然请求显示为200,但是不会返回任何数据,事实上简单来说请求同一个域名下的url或者说用不带http的绝对路径和相对路径请求是没有任何 ...