Seata
会有 4 种分布式事务解决方案,分别是AT
模式、TCC
模式、Saga
模式和XA
模式。
2019 年 1 月份,Seata
开源了AT
模式。AT
模式是一种无侵入的分布式事务解决方案。在AT
模式下,用户只需关注自己的业务SQL
,用户的 业务SQL
作为一阶段,Seata
框架会自动生成事务的二阶段提交和回滚操作。
ACID
事务的关系型数据库。Java
应用,通过 JDBC
访问数据库。两阶段提交协议的演变:
在一阶段,Seata
会拦截业务SQL
,首先解析SQL
语义,找到业务SQL
要更新的业务数据,在业务数据被更新前,将其保存成before image
,然后执行业务SQL
更新业务数据,在业务数据更新之后,再将其保存成after image
,最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
二阶段如果是提交的话,因为业务SQL
在一阶段已经提交至数据库, 所以Seata
框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
二阶段如果是回滚的话,Seata
就需要回滚一阶段已经执行的业务SQL
,还原业务数据。回滚方式便是用**before image
还原业务数据;但在还原前要首先要校验脏写,对比数据库当前业务数据**和 after image
,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
AT
模式的一阶段、二阶段提交和回滚均由Seata
框架自动生成,用户只需编写业务SQL
,便能轻松接入分布式事务,AT
模式是一种对业务无任何侵入的分布式事务解决方案。
TCC
模式2019 年 3 月份,Seata
开源了TCC
模式,该模式由蚂蚁金服贡献。TCC
模式需要用户根据自己的业务场景实现 Try
、Confirm
和Cancel
三个操作;事务发起方在一阶段 执行Try
方式,在二阶段提交执行Confirm
方法,二阶段回滚执行Cancel
方法。
TCC
三个方法描述:
Try
:资源的检测和预留;Confirm
:执行的业务操作提交;要求Try
成功Confirm
一定要能成功;Cancel
:预留资源释放。业务模型分 2 阶段设计:
用户接入TCC
,最重要的是考虑如何将自己的业务模型拆成两阶段来实现。
以扣钱场景为例,在接入TCC
前,对A
账户的扣钱,只需一条更新账户余额的SQL
便能完成;但是在接入TCC
之后,用户就需要考虑如何将原来一步就能完成的扣钱操作,拆成两阶段,实现成三个方法,并且保证一阶段Try
成功的话 二阶段Confirm
一定能成功。
如上图所示,
Try
方法作为一阶段准备方法,需要做资源的检查和预留。在扣钱场景下,Try
要做的事情是就是检查账户余额是否充足,预留转账资金,预留的方式就是冻结A
账户的 转账资金。Try
方法执行之后,账号A
余额虽然还是 100,但是其中 30 元已经被冻结了,不能被其他事务使用。
二阶段Confirm
方法执行真正的扣钱操作。Confirm
会使用Try
阶段冻结的资金,执行账号扣款。Confirm
方法执行之后,账号A
在一阶段中冻结的 30 元已经被扣除,账号A
余额变成 70 元 。
如果二阶段是回滚的话,就需要在Cancel
方法内释放一阶段Try
冻结的 30 元,使账号A
的回到初始状态,100 元全部可用。
用户接入TCC
模式,最重要的事情就是考虑如何将业务模型拆成 2 阶段,实现成TCC
的 3 个方法,并且保证Try
成功Confirm
一定能成功。相对于AT
模式,TCC
模式对业务代码有一定的侵入性,但是TCC
模式无AT
模式的全局行锁,TCC
性能会比AT
模式高很多。
Saga
模式Saga
模式是Seata
提供的长事务解决方案,由蚂蚁金服主要贡献。在Saga
模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。
Saga
模式下分布式事务通常是由事件驱动的,各个参与者之间是异步执行的,Saga
模式是一种长事务解决方案。
TCC
模式要求的三个接口XA
模式XA
模式是Seata
将会开源的另一种无侵入的分布式事务解决方案,任何实现了XA
协议的数据库都可以作为资源参与到分布式事务中,目前主流数据库,例如MySql
、Oracle
、DB2
、Oceanbase
等均支持XA
协议。
XA
协议有一系列的指令,分别对应一阶段和二阶段操作。 xa start
和 xa end
用于开启和结束XA
事务;xa prepare
用于预提交XA
事务,对应一阶段准备;**xa commit
和xa rollback
**用于提交、回滚XA
事务,对应二阶段提交和回滚。
在XA
模式下,每一个XA
事务都是一个事务参与者。分布式事务开启之后,首先在一阶段执行 xa start
、业务SQL
、xa end
和 xa prepare
完成XA
事务的执行和预提交;二阶段如果提交的话就执行 xa commit
,如果是回滚则执行xa rollback
。这样便能保证所有XA
事务都提交或者都回滚。
XA
模式下,用户只需关注自己的业务SQL
,Seata
框架会自动生成一阶段、二阶段操作;XA
模式的实现如下:
在XA
模式的一阶段,Seata
会拦截业务SQL
,在业务SQL
之前开启XA
事务(xa start
),然后执行业务SQL
,结束XA
事务**xa end
,最后预提交XA
事务(xa prepare
**),这样便完成 **业务SQL
**的准备操作。
执行**xa commit
指令,提交XA
事务,此时业务SQL
**才算真正的提交至数据库。
执行**xa rollback
指令,回滚XA
事务,完成业务SQL
**回滚,释放数据库锁资源。
XA
模式下,用户只需关注业务SQL
,Seata
会自动生成一阶段、二阶段提交和二阶段回滚操作。XA
模式和AT
模式一样是一种对业务无侵入性的解决方案;但与AT
模式不同的是,XA
模式将快照数据和行锁等通过 XA
指令委托给了数据库来完成,这样XA
模式实现更加轻量化。