10、分布式事务-Seata-AT模式-上

章节归属

分布式事务系列

1、背景

伴随着高性能的分布式系统演进,我们必然会经历 通过横向扩展节点 提高非热点数据的并发性能;而横向扩展节点实际是如下2方面的扩展变化:

  1. 扩展功能节点(对应应用的微服务化改造)
  2. 扩展数据节点(对应增加数据分片)

这些变化自然就引发 原来调用一个服务的一个接口就完成的功能,现在需要协同调用多个服务的多个接口才能完成。相信我们都遇到过因网络、机器、程序等不可靠,引发的数据一致性的问题。而数据的一致性与系统的可扩展性和高可用同样重要 是【基础IT架构】支撑业务高质量转型升级的重点也是难点。从蚂蚁金服的分布事务产品十几年的Roadmap可以看出其在数据一致性方面的坚持和不易(如今能快速使用他们的积累,幸甚至哉!),如下图所示:

image.png

从官宣得知,蚂蚁金服从微服务演进开始至今,大量的应用采用了TCC事务模型,2017年推出了FMT模式,类比即Seata中的AT模式。

2、起源

既然10年时间都是TCC模式,为什么会推出FMT(AT)模式呢,并且Seata官方也首推AT模式,注意AT是 Auto Transaction 的缩写,这个话题我觉得可以借助汽车从手动挡到自动挡的演进来讨论,早期全是自动挡汽车,但2021年统计显示自动挡车占比超过80%,为什么会这样呢:

  1. 自动档汽车比手动档汽车更容易操作
    自动档汽车可以自动匹配档位与速度,而手动档汽车则需要根据行驶速度,手动实现档位的转换。因此,自动档汽车更容易操作,更方便驾驶,尤其是对于缺少驾车经验的司机而言,自动档汽车是非常好的选择。
  2. 自动档汽车驾车舒适度更高
    自动档汽车不用进行手动换挡,不需要手和脚的密切配合。自动档汽车在驾驶时可以不用一直进行换档位,只需掌控踩油门的深浅,就可以轻松实现速度的转换,因此,很大程度上可以提高驾车舒适度。
  3. 自动档汽车安全系数更高
    对于新手来讲,让驾驶者专注于驾驶,避免额外的操控,做的少就错的少,错的少自然就降低事故率。

若将诞生于早期的TCC分布式事务模式类比成手动挡驾驶模式,那么Seata-AT模式就是当下主流的自动挡驾驶模式,正如有了自动变速箱后,驾驶者不需要知晓离合器、档位的存在,不用关注离合器、档位和油门三者之间那微妙协作;开发着不需要再去关心提供TCC三个方法,并掌控他们之间的协作;这些繁琐且难度高的事项由框架层托管,开发者只关注如何编写SQL来实现业务逻辑即可。

3、核心思想

Seata AT 模式 是基于数据源代理实现的,是增强型2pc模式;其核心思想就是由框架托管分布式事务:通过代理DataSource中的Connection,拦截SQL执行,改变其原执行逻辑,由代理引入额外的机制,加入额外的逻辑完成分布式事务。

4、角色和职责

4.1、基于JDBC驱动操作DB,提供服务

跟正常写业务服务没有区别。

4.2、角色

Seata-AT模式的实现中有3个重要角色

TC (Transaction Coordinator) - 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM (Transaction Manager) - 事务管理器(发起方)

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器(参与者)

提供TCC服务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

4.3、二阶段的职责分工

AT 模式对业务无任何侵入,其一阶段和二阶段的提交\回滚均由 Seata 框架自动生成,用户只需编写“业务 SQL”,便能轻松接入分布式事务。

image.png
4.3.1 第一阶段:

如下图所示,Seata 会拦截“业务 SQL”,首先解析 SQL 语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成“before image”,然后执行“业务 SQL”更新业务数据,在业务数据更新之后,再将其保存成“after image”,最后生成行锁。以上操作全部在一个本地数据库事务内完成,这样保证了一阶段操作的原子性。

image.png

第一阶段总结来说即是:业务sql和记录回滚日志的sql在同一个本地事务中提交,提交后即释放本地连接资源。

4.3.2. 第二阶段
4.3.2.1 二阶段-提交

因为“业务 SQL”在一阶段已经提交至数据库, 所以 Seata 框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。


image.png
4.3.2.2 二阶段-回滚

Seata 需要回滚一阶段已经执行的“业务 SQL”,还原业务数据。回滚方式便是用“before image”还原业务数据;但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。


image.png

第二阶段总结来说即是:TC向RM发起提交或回滚;提交的话通过异步进行回滚日志的自动清理,事务得以马上结束;回滚的话,通过一阶段的回滚日志,自动生成并执行补偿回滚的数据操作。

5、工作原理

5.1、整体架构

Seata-AT模式整体架构如下图所示:

image.png
5.2、核心流程
5.2.1、第一阶段
image.png

以一个原本有100块的账户扣掉10块钱为例:update account seg balance=balance-10 WHERE uId='001'

  1. 解析SQL:解析得到操作类型、表和条件,这里SQL操作类型是update,表是account,条件是uid='001' 信息
  2. 生成before image:从 account表中检索uId='001'的账户在执行update之前的余额,得到了100,即before image的结果集,作为回滚时使用的数据
  3. 执行业务SQL:update account set balance=balance-10 where uId='001'
  4. 生成after image:从 account表中检索uId='001'的账户的在执行update之后的余额,得到了90,即after image的结果集,作为回滚时用于比对判断是否有脏写的依据
  5. 记录undolog:将前后镜像组合,以 json格式压缩一下存到 UNDO_LOG 表中
  6. 提交前,RM向TC注册分支:这里会申请 account 表中主键值等于 '001' 的记录的全局锁,锁的粒度是:服务+表+记录ID
  7. 提交本地事务:将业务数据的更新和undolog的记录 一并提交
  8. 将本地事务提交的结果上报给 TC
5.2.2、第二阶段-提交
image.png
  1. TM 向 TC 发起全局事务提交
  2. TC 向 各RM 发起分支提交(传递XID)
  3. RM 接收到请求后放入一个异步任务的队列中,并立即返回TC提交成功
  4. 异步任务批量地删除相应 undolog
5.2.3、第二阶段-回滚
image.png
  1. 收到 TC 的分支回滚请求,开启一个本地事务
  2. 通过 XID 和 Branch ID 找到相应的 undolog
  3. 校验脏写:后镜像与当前数据库数据比较,如有不同则说明已被当前全局事务外的动作做了修改,此时需根据配置策略来处理
  4. 还原数据:根据前后镜像,生成逆向SQL并“回滚”(相当于重新写入一次)
  5. 删除undolog
  6. 提交本地事务,并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC
5.3、注意事项
  1. 空回滚、 防悬挂、 幂等控制
    在TCC模式下,需要考虑 空回滚、 防悬挂、 幂等控制的情况。但是在AT模式下,不需要有业务层去关注这些问题,因为框架可以通过AT模式中生成的前后镜像,自动处理以上问题。
  2. 数据隔离
    本地事务的支持是seata实现at模式的必要条件,在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted) ,通过 SELECT FOR UPDATE 语句实现读已提交 。

6、总结

跟TCC事务模式对比AT自动事务模式能带来这些好处:

  1. 难度低
    AT模式 对于缺少分布式事务经验的开发者来说,开发者仅按照传统开发模式,通过简单的注解就可委托框架层补充实现整个分布式事务,甚至不需要了解分布式事务的原理。
  2. 效率高
    AT模式,开发者专注于业务sql,只需要加注解就可实现分布式事务,而无需处理如TCC模式下的服务逻辑需拆分为try 、confirm和cancel三个部分;因此,很大程度上可以提高开发效率。
  3. 更安全
    拿TCC事务模型来说,要求开发者将服务拆分为try 、confirm和cancel三个部分,同时还要求开发者自身有缜密的设计和严谨的代码来控制事务安全,应对空回滚、幂等、悬挂等问题,并兼顾性能 ;而开发者对分布式事务的掌握程度不尽相同,自然实现的质量也很难保证。

缺点:

  1. 性能损耗
    前后两次查询,以及与TC的RPC通信,以及undo_log的写入,会增加更多的开销。
  2. 热点数据
    全局锁虽然是行锁,但对热点数据的读写依然不友好。

Seata AT和XA模式联系和区别

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容