分布式事务与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,它们对应 ...
随机推荐
- 段间跳转之TSS段
TR寄存器,TSS描述符,TSS段 TR寄存器与普通的段寄存器一样都有可见部分和不可见部分.TR的可见部分为16位为其段选择子,不可见部分是32位的TSS基地址和16位的大小. TSS描述符存在GDT ...
- 看雪加密解密第一个traceme程序破解
工具:ollydbg(吾爱破解2.10版) 工具设置:因为traceme是一个win32图形用户程序,所以其程序入口点在WinMain()函数处,设置ollydbg的调试设置的事件选项,选中在WinM ...
- 高阶函数 / abs方法
abs()求绝对值,填括号里面
- mysql多线程备份与还原工具mydumper
(一)mydumper介绍 之前我们已经学过如何使用mysqldump备份恢复数据库:<mysql逻辑备份与还原工具mysqldump>,就目前来说,mysqldump是使用最广泛的MyS ...
- Servlet-授课
1 Servlet 1.1 Servlet概述 Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一.我们可以像学习Java基础一样,通过API来学习Ser ...
- 【转载】深入理解OpenStack-手动制作qcow2镜像
深入理解OpenStack-手动制作qcow2镜像 2018-01-18 手动制作镜像 1 官方虽提供qcow2系统镜像,但对于有需求的企业来说,还是定制镜像比较靠谱,下面就手动定制一个镜像 给虚拟机 ...
- Linux软件安装管理之——dpkg与apt-*详解
Linux软件安装管理之--dpkg与apt-*详解 [Linux软件安装管理系列]- - 传送门: - -<Linux软件安装管理之--源码安装详解> - -<Linux软件安装管 ...
- linux各文件夹的作用-(转自玉米疯收)
linux下的文件结构,看看每个文件夹都是干吗用的 /bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的 ...
- Assignment Problem的若干思考
最近受到南京一个同学的push,又开始了博客园写作之旅.欢迎大家联系我做代码实现工作,QQ:1198552514.权当赚点生活费~ 我的研究也经常用的Assignment problem,而且很多 ...
- GO学习-(32) Go实现日志收集系统1
Go实现日志收集系统1 项目背景 每个系统都有日志,当系统出现问题时,需要通过日志解决问题 当系统机器比较少时,登陆到服务器上查看即可满足 当系统机器规模巨大,登陆到机器上查看几乎不现实 当然即使是机 ...