分布式事务专题:
1、什么是分布式事务?有几种?
- 分布式事务是指会涉及到操作多个数据库的事务,目的是为了保证分布式系统中的数据一致性。
- 分布式事务类型:二阶段提交2PC,三阶段提交3PC
- 2PC:准备阶段,提交阶段
- 3PC:cancommit、precommit、docommit
2、分布式事务的解决方案有哪些?
TCC、XA、AT、Saga
3、什么是TCC(Try-Confirm-Cancel)?
-
Try阶段:锁住要更改的资源,设置一个预备状态,冻结部分数据;
比如,订单的支付状态,先把状态修改为"支付中",本来库存100,现在卖出了2个,不要直接扣减这个库存,在表中设置一个冻结库存的字段,比如prepare_remove_stock字段,设置为2。也就是说有2个库存是给冻结了。
-
Confirm阶段:在各个微服务模块中,引入一个TCC分布式事务的框架,事务管理器可以感知到各个服务的Try操作是否都成功了。假如都成功了,TCC分布式框架会控制进入TCC下一个阶段,也就是Confirm阶段,此时,需要把Try阶段锁住的资源进行处理。
比如,把订单状态设置为"已支付",扣除掉相应的库存,将冻结库存的字段清零或者减掉相应库存。
-
Cancel阶段:在Try阶段,假如某个服务执行出错,TCC事务框架感知到后,开始对整个TCC分布式事务进行回滚。
比如,将订单的支付状态修改为"close"状态,冻结库存字段清零。
-
优点:一阶段完成之后,释放数据库资源,性能好,相比AT,无需生成快照,无需使用全局锁,性能最强,不依赖数据库事务,而是使用补偿操作,可以用于非事务型数据库。弱一致性。
-
缺点:有代码侵入,需要人为编写Try、Confirm、Cancel接口,软状态(base理论中的术语),需要考虑Confirm和Cancel的失败情况,做好幂等处理,会有脏读的可能
4、什么是XA?
是一个规范,目前主流数据库都实现了XA,其实现原理基于二阶段提交
- 一阶段:事务协调者通知每个事务参与者执行本地事务,但并不提交,并且持有数据库锁,之后将事务执行状态提交给事务协调者
- 二阶段:如果第一阶段所有分支事务(每个数据源对应的数据库操作)执行成功,则通知所有事务参与者,提交事务;如果第一阶段任意一个分支事务执行失败,则通知所有事务进行回滚
- 缺点:在全局事务执行过程中,会持有数据库锁,导致影响性能,XA模式依赖数据库机制实现回滚;XA模式强一致(同步等待的意思,对应CAP的C);
- 优点:不需要人工编写代码,侵入性小,不会产生脏读
5、什么是AT?
基于二阶段提交的分布式事务解决模型
- 一阶段:TM发起注册全局事务到TC,TM调用分支事务,分支事务准备执行业务sql,RM拦截业务sql,根据where条件查询原始数据形成快照(也就是数据库文件undo-log),RM执行业务sql并提交本地事务,释放数据库锁,RM报告本地事务状态给TC
- 二阶段:TM通知TC事务结束,如果分支事务都成功,则立即删除快照,如果任一分支事务失败,那么读取快照,恢复数据
- 优点:第一阶段提交数据,不锁定资源,性能好,利用全局锁和DB锁实现读写分离,没有代码侵入,框架自动提交和回滚
- 缺点:两阶段之间属于软状态,属于最终一致,框架的快照功能会影响性能,但是优于XA
6、什么是Saga?
Saga模式是Seata提供的长事务解决方案,业务流程中每个参与者都提交自己的本地事务,当出现某一分支事务失败,则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发自己实现
- 优点:一阶段提交本地事务,无锁,高性能,事件驱动架构,参与者可异步实现,高吞吐
- 缺点:需要写代码实现,比较麻烦;不保证隔离性
7、springboot对分布式事务的支持?
Atomikos(推荐)、 Bitronix
8、seata相关
- TC (Transaction Coordinator)-事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚
- TM (Transaction Manager)-事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务
- RM (Resource Manager)-资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚
9、TCC的事务悬挂和空回滚?
- 空回滚:当TCC分支事务Try阶段阻塞时,可能导致全局事务超时而触发二阶段的Cancel操作,在未执行Try操作时先执行了Cancel操作,这时Cancel不能叫回滚,而叫做空回滚。
- 事务悬挂:对于已经空回滚的业务,之前被阻塞的Try操作恢复,继续执行Try,就永远不可能Confirm或者Cancel,分支事务一直未被提交或者回退,处于这种中间状态的事务,叫做事务悬挂。
10、springboot使用的分布式事务注解?
@GlobalTransactional(rollbackFor = Exception.class)