目录
一、XA模式
【1】两阶段提交
【2】Seata的XA模型
【3】优缺点
【4】实现XA模式
二、AT模式
【1】Seata的AT模型
【2】AT与XA的区别
【3】脏写问题
【4】优缺点
【5】实现AT模式
一、XA模式
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准, XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA规范提供了支持。
【1】两阶段提交
XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
正常情况:
异常情况:
⼀阶段:
- 事务协调者通知每个事物参与者执行本地事务
- 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
⼆阶段:
- 事务协调者基于⼀阶段的报告来判断下⼀步操作
- 如果⼀阶段都成功,则通知所有事务参与者,提交事务
- 如果⼀阶段任意⼀个参与者失败,则通知所有事务参与者回滚事务
【2】Seata的XA模型
RM⼀阶段的工作:
- 注册分支事务到TC
- 执行分支业务sql但不提交
- 报告执行状态到TC
TC⼆阶段的工作:
- TC检测各分支事务执行状态
- 如果都成功,通知所有RM提交事务
- 如果有失败,通知所有RM回滚事务
RM⼆阶段的工作:
- 接收TC指令,提交或回滚事务
【3】优缺点
XA模式的优点是什么?
- 事务的强⼀致性,满足ACID原则。
- 常用数据库都支持,实现简单,并且没有代码侵⼊
XA模式的缺点是什么?
- 因为⼀阶段需要锁定数据库资源,等待⼆阶段结束才释放,性能较差
- 依赖关系型数据库实现事务
【4】实现XA模式
Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下:
1)修改application.yml文件(每个参与事务的微服务),开启XA模式:
seata:data-source-proxy-mode: XA
2)给发起全局事务的入口方法添加@GlobalTransactional注解:
本例中是OrderServiceImpl中的create方法.
3)重启服务并测试
重启order-service,再次测试,发现无论怎样,微服务都能成功回滚。
二、AT模式
【1】Seata的AT模型
基本流程图:
阶段⼀RM的工作:
注册分支事务
记录undo-log(数据快照)
执行业务sql并提交
报告事务状态
阶段⼆提交时RM的工作:
删除undo-log即可
阶段⼆回滚时RM的工作:
根据undo-log恢复数据到更新前
【2】AT与XA的区别
简述AT模式与XA模式最大的区别是什么?
XA模式⼀阶段不提交事务,锁定资源;AT模式⼀阶段直接提交,不锁定资源。
XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
XA模式强⼀致;AT模式最终⼀致
【3】脏写问题
在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题,如图:
解决思路就是引入了全局锁的概念在释放DB锁之前,先拿到全局锁,避免同⼀时刻有另外⼀个事务来操作当前数据。
【4】优缺点
AT模式的优点:
- ⼀阶段完成直接提交事务,释放数据库资源,性能比较好
- 利用全局锁实现读写隔离
- 没有代码侵⼊,框架自动完成回滚和提交
AT模式的缺点:
- 两阶段之间属于软状态,属于最终⼀致
- 框架的快照功能会影响性能,但比XA模式要好很多
【5】实现AT模式
AT模式中的快照生成、回滚等动作都是由框架自动完成,没有任何代码侵入,因此实现非常简单。 只不过,AT模式需要⼀个表来记录全局锁、另⼀张表来记录数据快照undo_log。
1)导入数据库表,记录全局锁
运行seata-at.sql,其中lock_table导入到TC服务关联的数据库,undo_log表导⼊到微服务关联的数据库:
2)修改application.yml文件,将事务模式修改为AT模式即可:seata:data-source-proxy-mode: AT # 默认就是AT
3)重启服务并测试
感谢你花时间读到这里~ 如果你觉得这篇内容对你有帮助,不妨点个赞让更多人看到;如果有任何想法、疑问,或者想分享你的相关经历,欢迎在评论区留言交流,你的每一条互动对我来说都很珍贵~ 我们下次再见啦!😊😊