当前位置: 首页 > ai >正文

Spring Cloud系列—Seata分布式事务解决方案AT模式

上篇文章:

Spring Cloud系列—Seata分布式事务解决方案XA模式https://blog.csdn.net/sniper_fandc/article/details/149947291?fromshare=blogdetail&sharetype=blogdetail&sharerId=149947291&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link

目录

1 AT模式原理

1.1 整体机制

1.2 写隔离

1.3 读隔离

2 AT模式使用

3 AT模式 VS XA模式


1 AT模式原理

1.1 整体机制

        AT模式是Seata针对两阶段提交2PC的改进模式,是一种非侵入式的分布式事务解决方案。通过引入数据源代理DataSourceProxy,在代理中添加undo_log日志和检查全局锁等逻辑,从而让RM不再需要数据库实现XA协议。改进后的2PC如下:

        一阶段:

        1.注册分支事务:TM开启全局事务,RM向TC注册分支事务;

        2.记录undo_log:执行SQL前首先会解析SQL,根据解析信息记录更新前镜像到undo_log,然后执行SQL记录更新后镜像到undo_log。记录undo_log的目的是因为一阶段会提交本地事务,因此如果要回滚就需要undo_log的支持(2PC需要实现XA协议,如果数据库没有实现该协议,就可能没有写undo日志和redo日志的行为)

        3.提交本地事务和undo_log:提交前获取全局锁(全局事务结束才会释放),然后直接提交本地事务(数据库数据会真实发生变化)。而2PC的一阶段只执行SQL不提交事务,因此2PC一阶段资源还会被锁定,到二阶段执行结束才会释放资源;AT模式在一阶段执行结束就会释放资源。

        4.汇报事务状态:RM向TC汇报本地事务(分支事务)的执行状态。

        二阶段:

        1.提交全局事务:如果所有分支事务都执行成功,则异步执行全局事务的提交和undo_log记录的清除。结束后RM向TC汇报状态,并释放全局锁。

        2.回滚全局事务:如果有分支事务执行失败,则开启本地事务进行回滚。回滚需要查询undo_log并比较当前数据和undo_log更新后镜像数据是否一致(如果不一致说明当前数据被其它全局事务修改,会根据配置策略来处理),如果一致就根据更新前镜像来回滚数据。结束后RM向TC汇报状态,并释放全局锁。

注意:AT模式其实就是在代理层面实现了没有在RM层面实现XA协议的回滚操作相关支持(即undo日志),同时引入全局锁来确保写隔离(不会出现赃写问题)。

1.2 写隔离

        当多线程并发操作同一个数据,就可能出现脏写问题。这是因为AT模式是一阶段就会提交本地事务,在全局事务未提交前,如果其它全局事务的分支事务对该数据修改,最终第一个全局事务提交后,该数据就变为第一个全局事务的值,从而丢失了其它全局事务的值。

        AT模式通过引入全局锁来解决脏写问题,实现写隔离:

        1.一阶段本地事务提交前,需要确保先拿到全局锁。

        2.拿不到全局锁,不能提交本地事务。

        3.拿全局锁的尝试被限制在一定范围内(超时时间或重试次数),超出范围将放弃,并回滚本地事务,释放本地锁。

        tx1全局事务先对m=1000的数据进行修改,本地事务首先要获取该数据的本地锁,执行m-100后为m=900,在提交本地事务前需要先获取全局锁,然后执行本地事务提交,提交成功后释放本地锁。

        tx2全局事务在tx1全局事务的二阶段前开启并执行,执行m-100后m=800(由于tx1一阶段会提交本地事务,因此tx2全局事务会读取m修改后的值),在提交本地事务前需要先获取全局锁,但是由于全局锁在tx1手里,因此就会不断重试获取全局锁。直到tx1事务提交全局事务后,才会释放全局锁,此时tx2才能获取全局锁进行本地事务提交。

        在事务执行成功的情况下,没有全局锁貌似没有问题。但是一旦tx1事务执行失败进行回滚,就会出现脏写。即tx2事务读取的是更新后回滚前的脏数据,tx1一旦回滚,tx2所做的任何操作都会无效。回滚情况下的工作模式如下:

        由于tx2更新后一直无法获取到tx1未释放的全局锁,但是tx2持有本地锁。而tx1想要回滚需要本地锁,但是其未释放全局锁。tx1和tx2就会相互等待,直到tx2获取全局锁超时(或超过重试次数),tx2本地事务就执行失败,进行回滚,并释放本地锁。tx1就能获取全局锁,从而进行回滚。

        总结:全局锁强制将两个阶段原子性执行,从而防止其它全局事务插入到该全局事务的两个阶段之间执行,避免了脏写问题。

1.3 读隔离

        多线程并发读/写,就可能出现脏读问题:即一个事务读到另一个事务读未提交的数据。要解决脏读问题,就需要事务隔离级别是读已提交。

        在数据库本地事务隔离级别读已提交(Read Committed)或以上的基础上,Seata(AT模式)的默认全局隔离级别是读未提交(Read Uncommitted)。

        如果应用在特定场景下,必需要求全局的读已提交,目前Seata实现读已提交事务隔离级别的方式是通过SELECT FOR UPDATE语句的代理。

        通过SELECT FOR UPDATE语句的代理查询tx1事务提交后的数据,该语句会获取全局锁,如果未获取到全局锁,说明事务未提交,就释放本地锁并阻塞等待,阻塞期间不断重试获取全局锁,此时读取的数据就是读已提交的数据,从而避免脏读问题。

        目前,Seata只对SELECT FOR UPDATE语句进行代理,并没有对其它查询语句代理,这是出于性能角度的考虑。

2 AT模式使用

        由于AT模式需要用到undo_log日志,因此需要创建undo_log表:

-- 注意此处0.7.0+ 增加字段 contextCREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

        使用AT模式仅需要修改配置文件:

seata:data-source-proxy-mode: AT

        当库存不足时,全局事务就会执行失败:

3 AT模式 VS XA模式

AT模式

XA模式

实现方式

1.通过记录数据镜像到undo_log日志表的方式来实现回滚

2.不需要数据库支持XA协议,但是需要创建undo_log日志表

1.需要数据库实现XA协议,依赖XA协议实现提交和回滚

2.不需要undo_log表,但是需要数据库支持XA协议

一致性

最终一致性:数据可能处于两阶段之间的中间状态

强一致性:数据的中间状态对用户不可见

性能

性能较好:一阶段直接提交,不锁定资源

性能较差:一阶段锁定资源,二阶段结束才释放

代码入侵

无代码入侵

无代码入侵

数据库支持

适用于几乎所有支持SQL的数据库

适用于实现XA协议的数据库

适用场景

性能要求高并且接受最终一致性场景

要求强一致性并且性能要求不高场景

下篇文章:

http://www.xdnf.cn/news/18133.html

相关文章:

  • 大模型落地选择困难症?RAG、Workflow、Agent全解析
  • Python脚本每天爬取微博热搜-终版
  • 在线客服系统访客表的设计与实现-增加最新消息字段
  • C#项目集成海康SDK指南:从搭建环境到实现视频预览、录制、截屏
  • 【LeetCode】16. 最接近的三数之和
  • 图论——Bellman-Ford和SPFA
  • 大模型+RPA:如何用AI实现企业流程自动化的“降本增效”?
  • traceroute命令使用指南
  • Linux学习-5网络管理
  • 企业如何让内部视频仅限指定域名播放,确保视频不被泄露?
  • SpreadJS 协同服务器 MongoDB 数据库适配支持
  • Flink Checkpoint 原理深度剖析与作用讲解(flink面试高频问题)
  • RK3128增加usb调试模式,开放adb和root权限
  • 分布式搜索(Elasticsearch)深入用法
  • 基于Python的宠物服务管理系统 Python+Django+Vue.js
  • 卫生许可证识别技术:通过OCR与NLP实现高效合规管理,提升审核准确性与效率
  • 传输层协议——UDP和TCP
  • 论文阅读:Prompt Optimization in Large Language Models
  • 传统概率信息检索模型:理论基础、演进与局限
  • 轻度娱乐浪潮下定制开发开源AI智能名片S2B2C商城小程序的机遇与策略
  • RNN(循环神经网络)和Transformer是处理自然语言处理(NLP)任务区别
  • 10.Ansible角色管理
  • 力扣2道dp
  • Rust 入门 生命周期-next2 (十九)
  • flask——4:请求与响应
  • Kubernetes(K8s)常用命令全解析:从基础到进阶
  • Unity进阶--C#补充知识点--【Unity跨平台的原理】Mono与IL2CPP
  • Disbursement on Quarantine Policy(概率、逆元计算期望)
  • 【深度学习】pytorch深度学习框架的环境配置
  • Ansible文件部署与大项目多主机管理