Seata是一款开源的分布式事务解决方案,星数19200+,社区活跃度高。分布式事务服务。目录的XA模式是什么?Seata的交易模式是什么?什么是AT模式?为什么Seata支持XA模式?AT与XA关系总结1.什么是XA模式?什么是XA,什么是Seata定义的事务模式,一目了然。1.1什么是XA用非常官方的话来说,XA规范是X/Open组织定义的分布式事务处理(DTP,DistributedTransactionProcessing)标准。XA规范描述了全局事务管理器和本地资源管理器之间的接口。XA规范的目的是允许在同一个事务中访问多个资源(如数据库、应用服务器、消息队列等),从而使ACID属性可以跨应用程序保持有效。XA规范使用两阶段提交(2PC,Two-PhaseCommit)来确保所有资源同时提交或回滚任何特定事务。XA规范是在1990年代初提出的。目前,几乎所有的主流数据库都支持XA规范。1.2Seata的交易模式是什么?Seata定义了全球交易的框架。一个全局事务定义为几个分支事务的整体协调:1.TM请求TC发起(Begin)、提交(Commit)、回滚(Rollback)全局事务。2、TM将代表全局事务的XID绑定到分支事务上。3、RM向TC注册,将分支事务与XID代表的全局事务相关联。4.RM向TC报告分支交易的执行结果。(可选)5.TC向RM发送分支提交(BranchCommit)或分支回滚(BranchRollback)命令。Seata的全局事务处理过程分为两个阶段:执行阶段:执行分支事务,并保证执行结果是Rollbackable和Durable的。完成阶段:根据执行阶段的结果形成的决议,将TM发出的全局提交或回滚请求应用到TC,TC命令RM驱动分支事务进行提交或回滚。Seata所谓的事务模式是指分支事务运行在Seata全局事务框架下的行为模式。准确的说,应该叫分支交易模式。不同事务模式的区别在于分支事务使用不同的方法来实现全局事务两个阶段的目标。即回答以下两个问题:执行阶段:如何执行并确保执行结果是Rollbackable和Durable。完成阶段:收到TC的命令后,做事务回滚/提交2.那么SeataXA模式是什么?XA模式:在Seata定义的分布式事务框架内使用事务资源(数据库、消息服务等)支持XA协议,利用XA协议的机制管理分支事务的事务模式。执行阶段:回滚:业务SQL操作放在XA分支,资源对XA协议的支持保证回滚持久化:XA分支完成后,执行XA准备。同样,资源对XA协议的支持,保证持久化(即任何意外都不会造成无法回滚的情况)完成阶段:分支提交:执行XA分支的提交分支回滚:执行XA分支的回滚XAbranch下面是模式2.1什么是SeataAT(TXC)模式?去年1月,Seata开源了AT模式。AT模式是一种非侵入式的分布式事务解决方案。AT模式下,用户只需要关注自己的“业务SQL”,用户的“业务SQL”作为第一阶段,Seata框架会自动生成事务的第二阶段提交和回滚操作.通过介绍其实可以发现AT模式的特点。只需要关注自己的业务sql,不侵入业务的分布式事务模式。那么我们应该知道他如何不侵入业务?2.2AT模式如何实现对业务的非侵入?AT模式第一阶段首先,在Seata组件中,如果你想开启分布式事务,那么你应该在你的业务入口或事务发起入口添加@GlobalTransactional注解。如果是AT模式,一定要做好数据源代理(seata1.0之后全面支持自动代理),通过sqlsessionfactroy(或者直接使用代理jdbc运行数据源)可以找到关键异步,区别于其他模式的是代理数据源,而代理数据源有什么玄机呢?如上图,你的数据源被代理后,被DataSourceProxy代理后,你执行的sql会被提取,解析,保存原像后,执行业务sql,然后保存图像,所以至于执行带有后续异常的两阶段回滚操作。2.3AT模式下如何保证隔离首先我们拿到官网展示的文档来更直观的描述一下:从上图可以得出:第一阶段提交本地事务之前,需要保证你首先获得全局锁。如果拿不到全局锁,就无法提交本地事务。获取全局锁的尝试被限制在一定范围内,超过范围则放弃,回滚本地事务,释放本地锁。两个全局事务tx1和tx2分别更新表a的m字段,m的初始值为1000。tx1先启动,启动本地事务,获取本地锁,更新m=1000-100=900。本地事务提交,先获取记录的全局锁,本地提交释放本地锁。启动tx2后,启动本地事务,获取本地锁,更新操作m=900-100=800。在本地事务提交之前,尝试获取记录的全局锁。在tx1被全局提交之前,记录的全局锁被tx1持有,tx2需要重试等待全局锁。如果tx2等待超时,那么tx2会将本地事务回滚到他不会产生脏数据。AT模式双阶段提交如果是第二阶段提交,因为“业务SQL”在第一阶段已经提交到数据库,Seata框架只需要删除第一阶段保存的快照数据和行锁就可以完成数据清理。AT模式两阶段回滚如果第二阶段是回滚,Seata需要回滚第一阶段已经执行过的“业务SQL”来恢复业务数据。回滚方式是使用“之前的映像”来恢复业务数据;但在恢复之前,必须先对脏写进行校验,将“数据库当前业务数据”和“残影”进行对比。如果两个数据完全一致,说明没有脏写,可以恢复业务数据。如果不一致,说明有脏写。如果有脏写,需要人工处理。Seata制定的交易模式下完整AT模型图:3.为什么支持XA?首先我们应该从AT来判断,为什么Seata即使有AT模式也支持XA从角度来看:首先,我们来总结一下AT模式,首先,所有的东西都是从TM发起的(不仅仅是AT)和读取和提交的数据只能在应用程序(用户开发的系统)中有效,资源的查看不能全面。XA让资源感知到自己已经在一个全局事务中,资源的隔离可以由数据库自己实现,满足全局一致性。从入侵和数据库支持的角度看:没有入侵,业务更彻底,服务操作少于两个,只能使用本地事务满足一致性,而AT需要全局锁来保证隔离,所以无论是一个服务,一个单一的数据库操作,或者n个服务,都需要启用全局事务来确保隔离。对于数据库支持,如果AT需要支持mysql、pgsql、oracle以外的数据库,则需要进行适配,复杂sql的分析成本较高,开发效率低,支持的sql数量少。XA可以完全支持数据库SQL语句,支持多种语言。如果你有使用过SeataXA的Java应用程序,那么本地数据库已经帮助我们确保了隔离。Seata不支持的其他语言即使和Java并行处理,数据也不会不一致。4.Seata为什么支持XA模式?数据加锁:在整个事务流程结束前,对涉及的数据进行加锁,根据隔离级别的定义限制读写。AT模式使用全局锁来保证基本的写隔离,真正对数据进行加锁,但是锁在TC端集中管理和解锁,效率高,无阻塞问题,而XA本地数据库可能会持有间隙锁,导致较小锁的粒度。大,锁多无辜数据死锁(协议阻塞):XAprepare后,分支事务进入阻塞阶段,必须阻塞等待,才能接收XA提交或XA回滚。如果没有可靠的协调者,比如abc的三个库的数据,决定在第二阶段提交。这时候ab收到的指令被提交了。c库收到指令后挂掉,不提交xa事务,或者协调器没有实现两阶段重试,那么未提交的xa事务会一直持有锁,从而造成死锁情况。性能差:性能损失主要来自两个方面:一方面是交易协调过程,增加单笔交易的RT;另一方面,并??发事务数据的锁冲突降低了吞吐量。其实主要是上面的阻塞和数据锁定,因为xa的第一阶段没有提交。如果提交第一阶段,at的性能优于xa,因为它被锁定在At模式。tc端集中释放,不需要多个库进行本地锁释放。AT和XA的关系首先要明确一点,无论是AT还是XA,都是利用数据库的事务特性来保证数据的一致性。而隔离,比如AT一阶段提交和两阶段回滚,都是执行本地事务。比如XA的第一阶段和第二阶段也是利用了数据库本身的事务特性,那么我们是不是应该在数据库层面深挖,AT和XA的关系呢?首先,这个时候,我们要找同,找异。AT首当其冲。他有一个必需品,就是undolog表,undolog。相信了解数据库的同学一定知道。数据库中有六种日志:redolog、undolog、binarylog、errorlog、slowquerylog、generalquerylog。log),relaylog(中继日志),那么数据库的undolog是干什么用的呢?undolog保存了事务发生前数据的一个版本,可以用于回滚,也可以提供多版本并发控制(MVCC)下的read,可以发现数据库的undolog与seata的undolog重合模式,所以可以判断at模式的undolog是利用undolog在本地事务中的作用,利用其原理实现分布式事务。保证了分布式事务下的事务一致性。那么说完undolog,那么redolog呢?redolog的作用是防止故障时将脏页写入磁盘。当mysql服务重启时,根据redolog进行redo,从而实现事务持久化这一特性。那么为什么SeataAT模式看不到redolog的存在呢?其实很简单,这个redolog隐藏的很深,就是AT方式的单阶段提交,让数据库作为我们的redolog,保证第一阶段的数据准确落盘。这时你会想到LCN交易模式吗?他的undolog是数据库保证的,缺少redolog。其实LCN交易大可不必错过。分析就到这里。如果第一阶段AT改成不提交,第二阶段提交,前镜像是undolog,后镜像是redolog。也就是说,AT其实不是数据库层面的。根据数据库事务的思路和实现原理,实现了分布式的事务一致性。这时候XA和AT的关系就应该清楚了。准确的说应该说是分布式事务和数据库本地事务的关系。可以说是XA的缺点导致了AT模式的诞生。side(多个库),资源阻塞,性能差。而AT就像是把事务执行的决策权从数据库放到了Seata,自己实现sql分析,自己实现undolog(redolog),既然分布式事务下我们没有办法直接优化数据库的问题,那么不如另辟蹊径,去其糟粕,取其精华。SeataAT和XA的优缺点其实上面说了很多各自的优缺点,都是点点滴滴。现在让我们将它们总结和比较为3点。SQL支持隔离和入侵。嗯,其实AT是一个自己实现的XA事务,所以我们其实可以知道,AT对SQL的支持远不如使用本地事务的XA模式。由于AT需要做SQL分析,后面的实现只能自己解决。也就是说,长期关键问题要靠Seata社区的贡献者贡献解决方案。但是很多用户还是选择重写SQL来获得对AT事务模式的支持。在sql支持方面,XA无疑是第二个隔离点。SeataAT方式获取解析sql涉及的主键id,生成行锁。即AT模式的隔离是通过全局锁来保证的,粒度细到行级。锁信息存储在Seata-Server端。XA模式的隔离由本地数据库来保证,锁存储在各个本地数据库中。XA模式一旦执行prepare,就不能再重新进入XA事务,也不能与其他XA事务共享锁。因为XA协议只是通过XID启动一个xa事务,它没有所谓的分支事务,它只是一个XA事务,也就是说它只关心自己。这时候,同学们可能会有疑惑。为什么我在branch_table中看到XA分支事务?其实这个问题可以从上面什么是Seata事务模式了解到,Seata的事务模式是由全局事务、分支事务、锁信息组成的。XA分支事务只作为参与者存在,也就是说XA分支是Seata定义中的分支事务,记录为分支信息,以便在宕机后下发二阶段解析信息。而AT,因为锁是自己实现的,相比XA,我只需要知道用户sql涉及的数据是否在数据的全局事务下。只要我默认,他就可以使用这把锁,也解决了问题。进入问题。我们可以得出结论,XA的隔离是全局的,AT的隔离更加灵活,相对全局(保证所有对数据的写操作都被Seata事务覆盖)。第三点是侵略性。通过以上信息,我们其实可以看出谁的级别低,谁的侵入性小。所以,数据库本身支持的XA模式无疑是侵入性最小的,使用成本也是最低的。其实说到这里,你可能会觉得XA模式感觉比AT好太多了。虽然不支持锁重入,但是我可以避免这种情况。这个时候我画一张图,你可能会更好的理解上面的图。右图1是at模式运行时,图2是xa模式运行时。显然,xa的阻塞带来的性能下降是非常严重的,尤其是如果你有很多分支事务,每个资源的释放必须等到每个分支的数据库分别释放,后续的事务才能进入。虽然XA带来的非侵入性很高,但是性能下降的程度太大,这也促使了AT的诞生,现在对AT、TCC、SAGA模式的接受度越来越高,这也表明开发者的性能要求。AT可以看作是Seata社区全方位优化的自研XA模式。最大的特点是解决了XA模式性能不佳的问题。TCC由Seata确定,用于两阶段状态通知。它的使用完全委托给用户,性能只有2个本地事务+一点点rpc开销。对于SAGA的整个交易环节,交易处理委托给用户进行编排,性能完全由用户来保证。Seata作为交易的协助方,记录全局交易的运行状态。可见,侵入性大的模式背后其实有更多的优化点,而侵入性小的模式会受到限制,只能依靠组件开发者进行不定期的优化来保证性能。综上所述,在目前的技术发展中,目前的分布式事务正在扮演东风,大量分布式、微服务,性能提升非常明显,但缺乏有利的保障,相信Seata是负责有了这样的角色,一切就绪。Seata项目的核心价值在于构建一个综合解决分布式事务问题的标准化平台。基于Seata,上层应用架构可以根据实际场景的需要,灵活选择合适的分布式事务方案。图片说明:本期分享基于西塔清冥、璇玑、一元三位PMC。分享者:陈建斌(funkye)githubid:a364176773作者介绍:同盾科技高级开发工程师,SeataCommitter,Springcloudalibabacontributor,Mybatis-Pluscontributor(bydynamic-datasource)
