seata源码-全局事务回滚服务端源码
这篇博客来记录在发起全局事务回滚时,服务端接收到netty请求是如何处理的
1. 发起全局事务回滚请求

在前面的博客中,有说到过,事务发起者在发现分支事务执行异常之后,会提交全局事务回滚的请求到netty服务端,这里是发送全局事务回滚请求的代码,同样,这里的GlobalRollbackRequest这个对象很重要,可以看到,在netty客户端这里,只入参了XID,这个xid贯穿了全局上下文,在服务端就是根据这里xid,来确定是要处理哪个全局事务
2. 服务端处理逻辑
在前面netty全局事务开启服务端源码中,有介绍过,netty服务端接收到客户端的请求之后,最终会进入到这个方法中,根据请求的对象类型,来决定是有哪个对象来处理

io.seata.server.AbstractTCInboundHandler#handle(io.seata.core.protocol.transaction.GlobalRollbackRequest, io.seata.core.rpc.RpcContext)
在这个方法中,会继续调度

可以发现,在doGlobalRollback方法中,最终,调用了core.rollback()

2.1 io.seata.server.coordinator.DefaultCore#rollback
在这里执行回滚的时候,有三个步骤
- 根据xid,找到netty服务端的globalSession
- 调用globalSession的close()方法,这个方法只是把globalSession的active属性设置为false了
- 最后会调用doGlobalRollback()方法,最核心的逻辑在这个方法中

2.2 doGlobalRollback
io.seata.server.coordinator.DefaultCore#doGlobalRollback
下面这是执行全局事务回滚的核心代码
- 会先根据全局事务,获取到所有的分支事务
- 然后依次遍历所有的分支事务
- 如果分支事务是失败状态,就直接删除分支事务(从branchTable中删除)
- branchRollback 这里是通过netty请求,触发分支事务进行回滚的逻辑,这个下面单独说
- 接着就会对分支事务回滚成功/失败,做出相应的处理;如果处理成功,会把branchTable和lockTable中的数据删除
- 最后在所有分支事务都处理之后,对全局事务进行处理,endRollbacked 在这个方法中,会把globalTable中的全局事务删除
public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {boolean success = true;// start rollback event 这里没看懂,先跳过eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC,globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus()));// 判断当前事务使用的模式if (globalSession.isSaga()) {success = getCore(BranchType.SAGA).doGlobalRollback(globalSession, retrying);} else {for (BranchSession branchSession : globalSession.getReverseSortedBranches()) {BranchStatus currentBranchStatus = branchSession.getStatus();if (currentBranchStatus == BranchStatus.PhaseOne_Failed) {/*** 1.如果分支事务是failed状态,直接remove,就是从branchTable表中删除记录*/globalSession.removeBranch(branchSession);continue;}try {/*** 2.调用客户端,进行分支事务回滚* 如果回滚成功,会在removeBranch中先删除lockTable的记录* 再删除branchTable的记录*/BranchStatus branchStatus = branchRollback(globalSession, branchSession);switch (branchStatus) {/*** 这是rm正常进行事务回滚的返回结果,如果rm进行了sql回滚,并且undolog日志正常删除* 那这里就会将lockTable和branchTable的记录删除*/case PhaseTwo_Rollbacked:globalSession.removeBranch(branchSession);LOGGER.info("Rollback branch transaction successfully, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());continue;case PhaseTwo_RollbackFailed_Unretryable:/*** rm抛出unretryable异常的话,会执行这里,将全局事务删除?*/SessionHelper.endRollbackFailed(globalSession);LOGGER.info("Rollback branch transaction fail and stop retry, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());return false;default:LOGGER.info("Rollback branch transaction fail and will retry, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());if (!retrying) {globalSession.queueToRetryRollback();}return false;}} catch (Exception ex) {StackTraceLogger.error(LOGGER, ex,"Rollback branch transaction exception, xid = {} branchId = {} exception = {}",new String[] {globalSession.getXid(), String.valueOf(branchSession.getBranchId()), ex.getMessage()});if (!retrying) {globalSession.queueToRetryRollback();}throw new TransactionException(ex);}}// In db mode, there is a problem of inconsistent data in multiple copies, resulting in new branch// transaction registration when rolling back.// 1. New branch transaction and rollback branch transaction have no data association// 2. New branch transaction has data association with rollback branch transaction// The second query can solve the first problem, and if it is the second problem, it may cause a rollback// failure due to data changes.GlobalSession globalSessionTwice = SessionHolder.findGlobalSession(globalSession.getXid());if (globalSessionTwice != null && globalSessionTwice.hasBranch()) {LOGGER.info("Rollbacking global transaction is NOT done, xid = {}.", globalSession.getXid());return false;}}if (success) {// 在这里的end方法中,会删除globalTable中的记录SessionHelper.endRollbacked(globalSession);// rollbacked eventeventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC,globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(),globalSession.getStatus()));LOGGER.info("Rollback global transaction successfully, xid = {}.", globalSession.getXid());}return success;
}
2.3 分支事务回滚 branchRollback(globalSession, branchSession);
io.seata.rm.DefaultResourceManager#branchRollback
服务端会通过发送netty请求(在2.2 中的branchRollback),触发rm这边开始进行分支事务的回滚,最终会在rm这边的这个类中进行分支事务回滚的操作
在执行回滚操作的时候,会根据branchType获取对应的manager

在这里,会根据当前的dbType,找到对应的undoLogManager,然后调用其undo方法进行分支事务回滚

io.seata.rm.datasource.undo.AbstractUndoLogManager#undo
在这里的undo方法中,会生成回滚sql,执行,然后删除undolog日志,代码太长了,但是逻辑不多,就不贴代码了
2.4 删除分支事务
我们接着上面2.2的逻辑来看,在调用netty请求,rm这一端进行了事务回滚之后,对于seata服务端这边,只需要把分支事务和全局事务删除即可
在2.2 的代码中,会对netty请求返回的状态进行判断,branchStatus
如果是PhaseTwo_Rollbacked,表示分支事务处理成功,此时会进入到globalSession.removeBranch(branchSession);来进行处理
在这个方法中,有两个逻辑,解锁和removeBranch,那就不用想了,肯定是删除分支事务加的锁和删除分支事务

io.seata.server.session.BranchSession#unlockio.seata.server.storage.db.lock.DataBaseLockManager#releaseLockio.seata.server.storage.db.lock.DataBaseLocker#releaseLock(java.lang.String, java.lang.Long)io.seata.server.storage.db.lock.LockStoreDataBaseDAO#unLock(java.lang.String, java.lang.Long)
对于释放锁的逻辑,比较简答,中间会调用的时候,会指定xid和branchId,然后去构建删除的sql

我们接着来看,删除分支事务的代码



这就是分支事务删除的逻辑;这个逻辑也比较简单,大部分都是共用的逻辑,就不做过多的介绍了
2.5 全局事务删除
SessionHelper.endRollbacked(globalSession);在这个方法中,会处理全局事务

这里看起来也有两个逻辑,在clean()方法中,我最开始没有看懂这个clean中要做什么,因为在clean中,就直接调用了下面截图中的这个releaselock方法,看到这个方法中的这行代码之后,我好像明白了,这里是再尝试将所有分支事务的锁进行释放的逻辑

我们接着来看,onEnd()的逻辑:



这就是全局事务删除的逻辑
总结
对于分布式事务,进行全局回滚的逻辑,还是比较简单的
- 在事务管理者这边发起全局事务回滚的请求
- seata服务端,也就是事务协调者接收到请求之后,会向所有的rm,发起netty请求,进行分支事务的处理
- 各个分支事务,会根据undoLog日志,生成回滚的sql,然后执行
- seata服务端在等分支事务返回状态之后,会先删除分支事务,在删除分支事务之前,会将分支事务加的锁给删除(这里的锁,如果是mysql的话,其实就是写入到mysql中的一条记录)
- 最后会去处理globalSession,将globalSession从mysql表中删除
所以其实分支事务回滚的时候,就是把全局事务 + 分支事务 + 锁 从mysql表中删除
相关文章:
seata源码-全局事务回滚服务端源码
这篇博客来记录在发起全局事务回滚时,服务端接收到netty请求是如何处理的 1. 发起全局事务回滚请求 在前面的博客中,有说到过,事务发起者在发现分支事务执行异常之后,会提交全局事务回滚的请求到netty服务端,这里是发…...
【Vue3源码】第一章 effect和reactive
文章目录【Vue3源码】第一章 effect和reactive前言1、实现effect函数2、封装track函数(依赖收集)3、封装reactive函数4、封装trigger函数(依赖触发)5、单元测试【Vue3源码】第一章 effect和reactive 前言 今天就正式开始Vue3源码…...
C函数指针
函数指针是指向函数的指针变量。通常我们说的指针变量是指向一个整型、数组或字符型等变量,而函数指针是指向函数。函数指针可以像一般函数一样,用于调用函数、传递参数。函数指针变量的声明:typedef int (*fun_ptr)(int,int); // 声明一个指…...
2023同等学力申请硕士计算机综合国考
同等学力国考报名要开始了 2023年2月15日,中国教育考试网和“全国同等学力人员申请硕士学位管理工作信息平台”(https://tdxl.chsi.com.cn,联系服务电话:010-67410388)公布报名工作通知。考生须按照通知要求进行注册或…...
英语基础-并列句概述
什么是并列句?并列句就是用连词把独立的句子连接起来,使得句子之间产生并列的逻辑。 1. 并列句中的逻辑 1. 小明步行上学,小红骑自行车上班。 Ming goes to school on foot,and Hong goes to work by bike. 平行逻辑 2. 小红经常玩手机…...
大数据框架之Hadoop:HDFS(一)HDFS概述
1.1HDFS产出背景及定义 HDFS 产生背景 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件…...
20230210组会论文总结
目录 【Ultra-High-Definition Low-Light Image Enhancement: A Benchmark and Transformer-Based Method】 【ShuffleMixer: An Efficient ConvNet for Image Super-Resolution】 【A Close Look at Spatial Modeling: From Attention to Convolution 】 【DEA-Net: Single i…...
Python - 数据容器dict(字典)
目录 字典的定义 字典数据的获取 字典的嵌套 字典的各种操作 新增与更新元素 [Key] Value 删除元素 pop和del 清空字典 clear 获取全部的键 keys 遍历字典 容器通用功能总览 字典的定义 使用{},不过存储的元素是一个个的:键值对&#…...
傻白探索Chiplet,文献阅读笔记汇总(十二)
Summary(方便分类管理) Article(文献出处) 方便再次搜索 Data(文献数据) 总结归纳,方便理解 Comments(对文献的想法)/Why(为什么看这篇文献)强…...
#电子电气架构——Vector工具常见问题解决三板斧
我是穿拖鞋的汉子,魔都中一位坚持长期主义的工科男。 今天在与母亲聊天时,得到老家隔壁邻居一位大姐年初去世的消息,挺让自己感到伤感!岁月如流水,想抓都抓不住。想起平时自己加班的那个程度,可能后续也要自己注意身体啦。 老规矩,分享一段喜欢的文字,避免自己成为高知…...
文本三剑客之grep
Grep是Linux用户用来搜索文本字符串的命令行工具。您可以使用它在文件中搜索某个单词或单词的组合,也可以将其他Linux命令的输出通过管道传输到grep,因此grep可以仅显示您需要查看的输出。grep的命令格式如下:grep 选项 查找条件 目标文件…...
pwn手记录题1
fuzzerinstrospector(首届数字空间安全攻防大赛) 主体流程(相对比较简单,GLibc为常见的2.27版本, Allocate申请函数(其中有两个输入函数Read_8Int、Read_context; 还存在着后门函数; 关键点在于如何利用…...
自动驾驶规划 - Apollo Lattice Planner算法【1】
文章目录Lattice Planner简介Lattice Planner 算法思路1. 离散化参考线的点2. 在参考线上计算匹配点3. 根据匹配点,计算Frenet坐标系的S-L值4. parse the decision and get the planning target5. 生成横纵向采样路径6. 轨迹cost值计算,进行碰撞检测7. 优…...
以太坊数据开发-Web3.py-安装连接以太坊数据
Web3.py是连接以太坊的python库,它的API从web3.js中派生而来。如果你用过web3.js,你会对它的API很熟悉。但惭愧的是,作为一个以太坊上Dapp的开发者,我几乎没有直接使用过web3.js,也没有看过它的API。 官网:…...
【触摸屏功能测试】MQTT_STD本地调试说明-测试记录
1、MQTT简介 MQTT是一种基于发布/订阅模式的“轻量级”通讯协议。它是针对受限的、低带宽的、高延迟的、网络不可靠的环境下的网络通讯设备设计的。 发布是指客户端将消息传递给服务器,订阅是指客户端接收服务器推送的消息。每个消息有一个主题,包含若干…...
六十分之十三——黎明前
目录一、目标二、计划三、完成情况四、提升改进(最少3点)五、意外之喜(最少2点)六、总结一、目标 明确可落地,对于自身执行完成需要一定的努力才可以完成的 1.8本技术管理书籍阅读(使用番茄、快速阅读、最后输出思维导图)2.吴军系列硅谷来信1听书、香帅的北大金融…...
【Call for papers】CRYPTO-2023(CCF-A/网络与信息安全/2023年2月16日截稿)
Crypto 2023 will take place in Santa Barbara, USA on August 19-24, 2023. Crypto 2023 is organized by the International Association for Cryptologic Research (IACR). The proceedings will be published by Springer in the LNCS series. 文章目录1.会议信息2.时间节…...
线程的信号量和互斥量
文章目录线程的信号量初始化信号量:sem_init减少信号量:sem_wait增加信号量:sem_post删除信号量:sem_destroy代码示例线程的互斥量初始化互斥量:pthread_mutex_init锁住互斥量:pthread_mutex_lock解锁互斥量…...
关于Linux,开源社区与国产化的本质区别
因为生产力驱动而非理想主义驱动。 开源运动的蓬勃发展来自于GNU(GNU is not unix),RichardMatthewStallman领导着一群黑客,带着对比尔盖茨的鄙视,制定了GPL协议,以后人人都能从伟大的前人身上学习到源代码的精髓,让软…...
Win11下Linux子系统迁移方法及报错解决
Win11 将Linux子系统从C盘迁移到其他盘Win11下Linux子系统迁移方法及报错解决1、下载LxRunOffline2、ERROR:directory is not empty 报错解决参考链接Win11下Linux子系统迁移方法及报错解决 C盘满了,Ubuntu子系统占了100多G怎么办?直接将子系…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
