分布式事务与Seate框架(3)——Seata的AT模式实现原理
前言
在上两篇博文(分布式事务与Seate框架(1)——分布式事务理论、分布式事务与Seate框架(2)——Seata实践)中已经介绍并实践过Seata AT模式,这里一些例子与概念来自这两篇(特别是第一篇理论部分),如果有不懂的小伙伴可以先看看,这里主要是讲解Seata AT模式的实现原理。
又好久没有记录博文了,这篇其实是很早之前就记录好了的,但是一直没时间去写出来,今天发出来算是再次对Seata分布式有个加深!
一、AT模式介绍
同样地,还是得先复习下分布式事务的相关理论部分:AT模式是Seata最主推的分布式事务且基于XA演进而来的解决方案,主要有三个角色:TM、RM和TC,其中TM和RM作为Seata的客户端和业务集成,TC作为Seata服务器独立部署。TM向TC注册一个全局事务,并生成全局唯一的XID;在AT模式下,数据库资源被当做RM,访问RM时,Seata会对请求进行拦截;每个本地事务提交时,RM会向TC(Transaction Coordinator,事务协调器)注册一个分支事务。
从三个角色TM、RM和TC的角度来记录具体的流程的话,可以总结如下:
- TM向TC注册全局事务,并生成全局唯一XID;
- RM向TC注册分支事务,并将其纳入到该XID对应的全局事务范围。
- RM向TC汇报资源的准备状态
- TC汇总所有事务参与者的执行状态,决定分布式事务全部回滚还是提交
- TC通知所有的RM提交/回滚事务
从具体的微服务角度总结,假设分别有三个:MicroService-1, MicroService-2, MicroService-3,流程图如下:

二、Seata AT模式的实现原理
1. AT模式的第一阶段实现
解析业务SQL,更新业务数据,保存更新前后镜像到undo_log。在业务操作数据库流程中,Seata会基于数据源代理(0.9以后支持自动代理)对原执行SQL进行解析。之后通过本地事务的ACID特性,将这两步操作(保存业务数据前后镜像到undo_log, 更新业务数据)在本地事务中进行提交。

比如(引用第二篇博文中的例子),我们对库存表库存进行减一,执行:
UPDATE repo SET amount=amount-1 WHERE id=1
则第一阶段需要做的步骤:
(1)通过DataSourceProxy对业务SQL进行解析,得到SQL的表、WHEER条件等,之后通过查询修改之前的数据:
SELECT id, name, amount, price FROM repo WHERE id=1;
这样就得到了修改之前的镜像,此时amount=100;
(2)执行更新业务:
即执行update语句,此时amount=99;
(3)查询修改之后的数据镜像,此时是通过第二步获取到的主键查询到修改之后的数据的
SELECT id, name, amount, price FROM repo WHERE id=1;
这样就有了修改之后的数据镜像了。
(4)插入回滚日志
有了修改前后的业务镜像数据之后,可以将业务镜像数据与业务相关的SQL信息构造成一条undo_log记录,插入undo_log表中:

(如果要看到undo_log记录,则需要在debug模式下或者日志打印输出,否则事物回结束后会删除该记录)
(5)向TC注册分支事务,并且申请关于id=1记录的全局锁
(6)本地事务开始提交,将undo_log数据插入与更新业务数据一并提交(只有释放全局锁)
(7)将本地事务提交的结果告诉TC。
从AT模式的第一阶段来看,不同于XA模式的主要有以下几点(或者说优势):
- 分支事务在第一阶段提交完成之后就马上释放本地事务锁定的资源。而XA模式一般是在锁定资源的持续到第二阶段的提交或者回滚后才释放资源。
- AT模式第一阶段就释放了资源,这样就会让AT模式提升了分布式事务处理效率;
- 之所以在第一阶段就释放了资源,这是因为AT模式下,在第一阶段就记录了undo_log回滚日志,所以不怕第二阶段出现异常。
2.AT模式第二阶段的原理分析
TC服务接收到事务分支的事务状态汇报之后,决定对全局事务进行提交或者回滚,这就是第二阶段。
2.1.事务提交
如果在第一阶段所有的分支事务已经提交,则TC决定全局事务提交,此时只需要清理UNDO_LOG日志即可,相比较XA模式,不需要TC触发所有分支事务的提交。

具体的流程为:
(1) 分支事务收到TC的提交请求之后放入异步队列中,马上返回提交成功的结果;这里不需要同步返回的原因是:TC不需要知道分支事务的结果,因为仅仅只是一步删除UNDO_LOG记录的操作,即使不成功也不会结果造成影响,所以采用异步是有效的方式。
(2) 从异步队列中执行分支提交请求,清理undo_log日志,这里并不需要分支事务的提交了,因为第一阶段中已经提交过了。
理解起来就是:AT模式下的全局事务的提交只需要清理UNDO_LOG记录就行,不需要管分支(本地)事务的提交结果!
2.2.事务回滚
在第一阶段的分支事务中任何一个分支事务执行失败,都会进入全局事务回滚流程,显而易见全局事务的回滚主要是依赖UNDO_LOG中的记录进行补偿的。

具体的流程如下:
接收到TC的回滚请求后,开启本地事务用来执行回滚操作
(1)本地事务分支开始进行对查找UNDO_LOG记录
通过XID+branch ID查到UNDO_LOG记录;
(2)数据校验(对比更新后镜像数据与当前数据)
拿到rollback_for中afterImage镜像数据与当前业务表中数据比较,不同的话,比如afterImage镜像数据拿出的amount理论上为99,但是实际上amount=98,则说明已经被当前全局事务外的某个操作做了修改(实际上由于全局锁的存在,并不会存在其他全局事务对业务数据进行更新),那么事务不进行回滚。
(3)第二步中对比结果是相等的话,就采用beforeImage和SQL的相关信息进行回滚,即:
UPDATE rep SET acoumt=100 WHERE id=1
(4)删除UNDO_LOG记录
(5)提交本地事务
(6)将本地事务的回滚执行结果报告给TC
3.AT模式下事务的隔离性保证
在AT模式下,多个全局事务操作同一张表时,它的事务隔离性保证是基于全局锁来实现的。
(1)写隔离
在第一阶段本地事务提交之前,必须确保拿到全局锁,如果拿不到全局锁则一直等待尝试,超出最大尝试次数则放弃全局锁的获取,并回滚释放本地锁(在本地事务开始之前就获到本地锁,这里的本地锁概念是数据库锁,比如对某行记录的行锁)
(2)读隔离
数据库不设置事务隔离级别下发生三种情况(相当于复习下数据库隔离级别相关理论知识):
脏读:脏读是指一个事务在处理数据的过程中,读取到另一个未提交事务的数据。
不可重复读:不可重复读是指对于数据库中的某个数据,一个事务范围内的多次查询却返回了不同的结果,这是由于在查询过程中,数据被另外一个事务修改并提交了。
幻读:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。也就是第一个事务读取的时候发现其他事务插入(或删除)的事务,就跟幻觉一样。
幻读跟不可重复读都是读取了另一个事务提交的结果,而不可重复读的重点是修改,幻读的重点在于新增或者删除。
在数据库本地事务隔离级别为RR或者以上时,Seata AT事务模式的默认全局隔离级别是Read Uncommit,在这种隔离级别下,所有事务都可以看到其它未提交事物的执行结果产生脏读,这在最终一致性的事务模型是被允许的,并且大部分是分布式事务是接受脏读的。
分布式事务与Seate框架(3)——Seata的AT模式实现原理的更多相关文章
- 分布式事务与Seate框架(2)——Seata实践
前言 在上一篇博文(分布式事务与Seate框架(1)--分布式事务理论)中了解了足够的分布式事务的理论知识后,到了实践部分,在工作中虽然用到了Seata,但是自己却并没有完全实践过,所以自己私下花点时 ...
- 分布式事务与Seate框架(1)——分布式事务理论
前言 虽然在实际工作中,由于公司与项目规模限制,实际上所谓的微服务分布式事务都不会涉及,更别提单独部署构建Seata集群.但是作为需要不断向前看的我,还是有必要记录下相关的分布式事务理论与Seate框 ...
- 分布式事务(七)之Seata简介
在前面的文章中,我们介绍了分布式事务的概念以及一些解决方案.fenSeata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata将为用户提供了AT.TCC.SAGA和 ...
- Spring Cloud同步场景分布式事务怎样做?试试Seata
一.概述 在微服务架构下,虽然我们会尽量避免分布式事务,但是只要业务复杂的情况下这是一个绕不开的问题,如何保证业务数据一致性呢?本文主要介绍同步场景下使用Seata的AT模式来解决一致性问题. Sea ...
- 分布式事务解决方案,中间件 Seata 的设计原理详解
作者:张乘辉 前言 在微服务架构体系下,我们可以按照业务模块分层设计,单独部署,减轻了服务部署压力,也解耦了业务的耦合,避免了应用逐渐变成一个庞然怪物,从而可以轻松扩展,在某些服务出现故障时也不会影响 ...
- 开发者说 | 分布式事务中间件 Seata 的设计原理
导读 微服务架构体系下,我们可以按照业务模块分层设计,单独部署,减轻了服务部署压力,也解耦了业务的耦合,避免了应用逐渐变成一个庞然怪物,从而可以轻松扩展,在某些服务出现故障时也不会影响其它服务的正常运 ...
- 微服务痛点-基于Dubbo + Seata的分布式事务(AT)模式
前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...
- 微服务痛点-基于Dubbo + Seata的分布式事务(TCC模式)
前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...
- 浅谈,seata在使用feign-url通过域名调用时分布式事务不生效的问题及解决
浅谈,seata在使用feign-url通过域名调用时分布式事务不生效的问题及解决 在前几个月时,我们项目出现了分布式事务的问题,那么什么是分布式事务问题呢,简单的说,我们有俩服务A和B,它们对应 ...
随机推荐
- Go的Waitgroup和锁
学 Go 的时候知道 Go 语言支持并发,最简单的方法是通过 go 关键字开启 goroutine 即可.可在工作中,用的是 sync 包的 WaitGroup,然而这样还不够,当多个 gorouti ...
- PTA 第三章 栈与队列
一.判断题 1.若一个栈的输入序列为1,2,3,--,N,输出序列的第一个元素为i,则第j个输出的元素是j-i-1 (×)解析:应该是不确定的,不能保证数字出栈后不会再入栈 2.所谓" ...
- 从系统的角度分析影响程序执行性能的因素——SA20225205 黄兴宇
实验总结分析报告:从系统的角度分析影响程序执行性能的因素 1.请您根据本课程所学内容总结梳理出一个精简的Linux系统概念模型,最大程度统摄整顿本课程及相关的知识信息,模型应该是逻辑上可以运转的.自洽 ...
- 游戏视野系统算法 (FOV using recursive shadowcasting)
原理 http://www.roguebasin.com/index.php?title=FOV_using_recursive_shadowcasting python代码实现 http://www ...
- 【2020BUAA软件工程】个人博客作业
个人作业博客 项目 内容 北航2020软工 班级博客 作业要求 具体要求 我的课程目标 学习软件工程,掌握团队合作,锻炼自我 作业在哪个方面帮助我实现目标 通读<构建之法>,尝试理解软件工 ...
- .Net平台的GC垃圾回收
一.先了解下必备的知识前提 内存中的托管与非托管,可简单理解为: 托管:可借助GC从内存中释放的数据对象(以下要描述的内容点) 非托管:必须手工借助Dispose释放资源(实现自IDisposable ...
- 24.Qt Quick QML-Canvas和Context2D详解
1.Canvas介绍Canvas是一个允许绘制直线和曲线.简单和复杂的形状.图形和引用的图形图像.它还可以添加文本.颜色.阴影.渐变和图案,并执行低级别像素操作.Canvas输出可以另存为图像文件或序 ...
- [Java] 数据分析 -- 大数据
单词计数 需求:输入小说文本,输出每个单词出现的次数 实现:分map.combine.reduce三个阶段实现 1 /* Data Analysis with Java 2 * John R. Hub ...
- Python检查 文件备份是否正常 云备份进程是否正常运行
场景:服务器自动备份数据库文件,每两小时生成一个新备份文件,通过云备份客户端自动上传,需要每天检查是否备份成功. 实现:本脚本实现检查文件是否备份成功,进程是否正常运行,并且发送相关邮件提醒. #! ...
- VMware安装RedHat7、CentOS7后无网卡解决办法
由于Vmware虚拟网卡和linux兼容问题导致驱动无法正常安装,默认的网卡类型不兼容找到我们的Vmware虚拟机文件夹,将VMware 虚拟机配置 (.vmx),追加一条设置,网卡类型etherne ...