SeataAT模式原理
Seata架构
Seata将分布式事务理解为一个全局事务,它由若干个分支事务组成,一个分支事务就是一个满足ACID的本地事务。
Seata架构中有三个角色:
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
刚入门时,可能不太理解这三个角色的关系,举个例子来描述:假设我们有一个下单业务,用户发起下单(Create_Order)后需要进行支付扣款,扣库存。Create_Order需要调用其他两个服务进行数据的更新。
这里OrderService这个微服务就是TM,它发起了全局事务, 库存和支付都是事务的参与者,也就是RM,而全局事务的进行需要TC协调两个RM完成
下图能更直观地感受它们的分工:
(图侵删)
简单说明全局事务的执行过程:
- TM向TC申请开启一个全局事务,TC创建全局事务后,会生成一个全局唯一的XID,存入
global_table中。 XID会在全局事务上下文中传播 - RM请求TC将本地事务注册成全局事务的分支事务,该分支事务和全局事务有相同的XID
- TM向TC发起全局提交或回滚
- TC调度XID下的分支事务完成提交或回滚。
AT模式
AT模式是Seata默认模式。它从两阶段提交演化而来,改善了XA模式中资源占用过长导致性能下降的问题。
和XA的区别:AT模式下的第一阶段RM将在执行完事务后,会保存记录一份快照,然后直接提交并释放资源,若第二阶段通知事务需要回滚,再进行反向补偿,修改为提交前的数据。
在这个过程中,Seata做了不少增强:我们的业务Sql实际上不是直接就在DB中运行,而是被Seata的数据源代理拦截,那么Seata做了什么工作呢,我们接下来继续说:
第一阶段:
- Seata拦截业务sql并解析,根据解析到的信息去查询数据库得到更新前的数据镜像,称为before image。
- 再获取一次执行完后的数据,称为after image
- 将before_image和after_image的数据都插入到 undo_log表中
- 在事务提交前,向TC注册分支,申请获得数据库被写的行的全局锁
- 提交本地事务和undo_log表,并将本地事务提交结果报告给TC
第二阶段:
- 二阶段提交:若事务全部执行成功,RM就可以删除undo_log表并直接提交了。
- 二阶段回滚收到TC的回滚请求,则根据undo_log表中的
befor_image和业务sql的相关信息生成回滚语句在数据库中执行。 进行数据的回滚。
这样一来,事务就不需要一直占用着本地锁了,而是引用了全局锁对数据库的某行进行锁定。接下来我们介绍AT模式下脏写和脏读的问题
AT模式的脏读问题
当我们不引入全局锁,来看两个线程:

很明显,线程2就发生了脏读。如何解决? Seata引入了全局锁的概念:一阶段分支事务提交前,需要申请获得数据库的全局锁(锁定的是被修改的行),在二阶段中如果有其他线程想要修改这一行的数据,除了获取本地锁之外,还需要申请得到全局锁才能修改数据,如下图:

也许有同学会问,如果tx1拥有全局锁,二阶段回滚想要获取本地锁,同时tx2拥有本地锁而想要获取全局锁,那不就死锁了吗?不会,因为Seata给申请锁添加了超时放弃的机制:图中tx2申请全局锁超时后,事务回滚释放了本地锁,tx1获得本地锁成功回滚。

AT模式脏写问题
和脏读类似,如果不引入全局锁,tx1一阶段修改了数据库某行并提交,在第二阶段tx2先进入修改了该行。过后tx1如果要利用快照回滚,tx2就发生了脏写。
Seata引入了全局锁后,一阶段本地事务提交前,需要确保先拿到全局锁,只有拿到全局锁才能提交,在二阶段如果需要回滚,全局锁在事务隔离上就派上了用场:

上图中tx2尝试获取全局锁失败后回滚,tx1重试多次后终于拿到本地锁回滚成功。这个过程中由于全局锁一直由tx1持有,不会出现脏写问题。
参考链接:
Seata AT 模式
SpringCloud实践:Seata分布式事务
SeataAT模式原理的更多相关文章
- Spark基本工作流程及YARN cluster模式原理(读书笔记)
Spark基本工作流程及YARN cluster模式原理 转载请注明出处:http://www.cnblogs.com/BYRans/ Spark基本工作流程 相关术语解释 Spark应用程序相关的几 ...
- 深度分析Linux下双网卡绑定七种模式 多网卡的7种bond模式原理
http://blog.csdn.net/abc_ii/article/details/9991845多网卡的7种bond模式原理 Linux网卡绑定mode共有七种(~) bond0.bond1.b ...
- 多网卡的7种bond模式原理
多网卡的7种bond模式原理 Linux 多网卡绑定 网卡绑定mode共有七种(0~6) bond0.bond1.bond2.bond3.bond4.bond5.bond6 常用的有三种 mode=0 ...
- lvs-dr模式原理详解和可能存在的“假负载均衡”
原文地址: http://blog.csdn.net/lengzijian/article/details/8089661 lvs-dr模式原理 转载注明出处:http://blog.csdn.net ...
- 多网卡的7种bond模式原理 For Linux
多网卡的7种bond模式原理 Linux 多网卡绑定 网卡绑定mode共有七种(0~6) bond0.bond1.bond2.bond3.bond4.bond5.bond6 常用的有三种 mode=0 ...
- 【转载】多网卡的7种bond模式原理
多网卡的7种bond模式原理 Linux 多网卡绑定 网卡绑定mode共有七种(0~6) bond0.bond1.bond2.bond3.bond4.bond5.bond6 常用的有三种 mode=0 ...
- go--->共享内存和通信两种并发模式原理探究
共享内存和通信两种并发模式原理探究 并发理解 人类发明计算机编程的本质目的是为了什么呢?毫无疑问是为了解决人类社会中的各种负责业务场景问题.ok,有了这个出发点,那么想象一下,比如你既可以一心一意只做 ...
- LVS负载均衡NAT模式原理介绍以及配置实战
LVS基本原理 流程解释: 当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间 PREROUTING 链首先会接收到用户请求,判断目标 IP 确定是本机 IP ...
- LVS 三种工作模式原理、以及优缺点比较(转载)
原文地址:http://9ilinux.com/149.html 一.NAT模式(VS-NAT) 原理:就是把客户端发来的数据包的IP头的目的地址,在负载均衡器上换成其中一台RS的IP地址,并发至此R ...
随机推荐
- JavaScript 中 append()、prepend()、after()、before() 的区别
内容 append().prepend().after().before() 的区别 jQuery 操作 DOM 之添加节点 方法名 作用 $(selector).append() 指定元素内部添加, ...
- wx.getImageInfo和wx.downloadFile下载用户头像报错(小程序canvas以及小程序图片下载部分)
我先上图 之前我们后台配置的 downloadFile 合法域名是 https://wx.qlogo.cn, 用了好久都没出问题, 前段时间, 用户反馈 分享海报, 用户头像出不来!!!! ...
- vue中执行npm run build报错解决方法?
遇到了执行npm run build 后报错: [build:js ] Module not found: Error: Can't resolve 'scss-loader' in 'D:\work ...
- 「进阶篇」Vue Router 核心原理解析
前言 此篇为进阶篇,希望读者有 Vue.js,Vue Router 的使用经验,并对 Vue.js 核心原理有简单了解: 不会大篇幅手撕源码,会贴最核心的源码,对应的官方仓库源码地址会放到超上,可以配 ...
- power app 解决方案中表导入问题
我们在powerapp中导出的表,解压后是会是乱码,导致在导入的时候会失败,或者导入数据不全. 使用 2 但是直接导入也会是乱码,所以需要将文件重新保存一下: 首先新建一个excel 选择要导入的那个 ...
- 帝国CMS网站地图生成插件
可以生成电脑端也可以生成手机端的地图XML. 安装方法: 这个帝国sitemap插件的安装跟其他插件的安装方式一样,介于可能有人不会安装帝国的插件,就写一下吧,以后你们如果碰到帝国插件也可以参考这个. ...
- 从电路到UI系列之一——常见显示控制接口的认识
引入 我之前有两方面的使用屏幕的案例.在做的模块上需要用到屏幕来显示的时候,全是SPI屏幕,并口屏幕和IIC屏幕.在研究了驱动(或者是绘图函数更加合适)之后,我发现其实他们就是直接写显存,这个显存在面 ...
- 安卓记账本开发学习day10
完成了最后一部分功能 1.柱状分析每月的支出或收入 2. 删除所有记录
- go interface{}使用
先上代码 func In(haystack []interface{}, needle interface{}) (bool, error) { sVal := reflect.ValueOf(hay ...
- android软件简约记账app开发day02-收入支出明细页面绘制
android软件简约记账app开发day02-收入支出明细页面绘制 效果图 列表界面绘制 新建layout文件-item_mainlv.xml大体使用绝对布局,嵌套相对布局,嵌套文本内容实现 < ...