Seata之AT模式
目录
AT模式的引进
我们XA模式有死锁(协议阻塞)问题:XA prepare 后,分支事务进入阻塞阶段,收到 XA commit 或 XA rollback 前必须阻塞等待。如果没有一个靠谱的协调者存在,比如abc三个库的数据被二阶段决议为提交,此时ab收到的指令,提交后,c库在收到指令后挂了,并没有提交xa事务,或者协调者没有做到二阶段重试,那么这个没有提交的xa事务将会一直 持有锁,造成死锁的局面。在这里我们将会引进AT模式,解决同步阻塞等问题。
seata的AT模式是一个无侵入的分布式事务。
AT模式前提
- 基于支持本地 ACID 事务的关系型数据库。
- Java 应用,通过 JDBC 访问数据库。
AT模式的工作流程
AT模式是基于一个全局的事务管理器来管理的。例如,在全局事务下,当我们存在A,B两个服务的时候,A和B的提交都会生成一个undo_log的记录,会记录下执行前和执行后的镜像,如果一段提交没有错误的话,则会进行二段提交,如果在全局事务中有异常抛出,则根据undo_log进行回滚。
阶段一RM的工作:
-
注册分支事务
-
记录undo-log(数据快照)
-
执行业务sql并提交
-
报告事务状态
阶段二提交时RM的工作:
-
删除undo-log即可
阶段二回滚时RM的工作:
-
根据undo-log恢复数据到更新前
案例流程梳理
我们用一个真实的业务来梳理下AT模式的原理。
比如,现在又一个数据库表,记录用户余额:
id | money |
---|---|
1 | 100 |
其中一个分支业务要执行的SQL为:
AT模式下,当前分支事务执行流程如下:
一阶段:
(1)TM发起并注册全局事务到TC
(2)TM调用分支事务
(3)分支事务准备执行业务SQL
(4)RM拦截业务SQL,根据where条件查询原始数据,形成快照。
(6)RM执行业务SQL,提交本地事务,释放数据库锁。此时 money = 90
(7)RM报告本地事务状态给TC
二阶段:
(1)TM通知TC事务结束
(2)TC检查分支事务状态
(a)如果都成功,则立即删除快照
(b)如果有分支事务失败,需要回滚。读取快照数据({"id": 1, "money": 100}
),将快照恢复到数据库。此时数据库再次恢复为100
AT模式的原理
- 事务的发起者开始一个全局事务,并在本地事务管理器中开始一个本地事务。
- 事务的发起者调用其他参与者的服务,将全局事务ID传递给它们。
- 参与者接收到全局事务ID后,在本地事务管理器中开始一个本地事务,并执行操作。
- 当参与者的本地事务执行成功时,将操作结果记录在本地日志中。
- 事务的发起者完成所有参与者的服务调用后,调用各个参与者的提交接口。
- 参与者检查本地事务的日志记录,如果操作都成功,则提交本地事务;否则,回滚本地事务。
具体使用
修改application.yml文件(每个参与事务的微服务),开启XA模式:
给发起全局事务的入口方法添加@GlobalTransactional注解:
优缺点
优点
:
-
较高的性能:AT模式在每个参与者的本地事务中执行操作,避免了全局锁和阻塞的问题,提高了系统的并发性能。
-
简化的实现:相对于XA模式,AT模式的实现相对简单,不需要涉及全局事务协调器,减少了开发和维护的复杂性。
-
本地事务的独立性:每个参与者在本地事务管理器中管理自己的事务,可以独立控制和优化本地事务的执行。
缺点
:
-
弱一致性:AT模式对一致性的要求相对较低,可能会出现数据不一致的情况。在某些场景下,可能需要更高的一致性保证,需要考虑其他分布式事务处理模式。
-
隔离级别限制:由于AT模式依赖于本地事务的隔离性,参与者的隔离级别受限于本地事务管理器支持的隔离级别,可能无法满足某些特定的隔离需求。
-
容错性和恢复性:AT模式在发生故障或错误时,需要考虑如何处理事务的回滚和恢复,以确保数据的一致性和可靠性。
小结
性能:高
模式:AP,存在数据不一致的中间状态
难易程度:简单,靠SEATA自己解析反向SQL并闻滚
使用要求:
- 所有服务与数据库必须要自己拥有管理权,因为要创建UNDO LOG表
应用场景:
- 高并发互联网应用,允许数据出现短时不一致,可通过对账程序或补录来保证最终一致性。
- 点赞
- 收藏
- 关注作者
评论(0)