文章目录
一、Spring Cloud Seta是什么?
官网:https://seata.io/zh-cn/docs/overview/what-is-seata.html
官方解读:Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
也就是说:由于在当前的项目中可能存在多个分布式事务,可以对某些服务注明回滚防止发生异常,但其他被调用的事务就不会进行回滚,因此可能会出现脏读等现象。为了合理的解决分布式事务问题,Seata就迎刃而出。
二、Seata的AT模式处理分布式事务方式
1.三个模块
TC(Transaction Coordinatiion):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚
TM(Transaction Manager):控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议
RM(Resource Manager):控制分支事务,负责分支注册,状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚
三个角色解读:
TC相当于老师,负责整个班级(整个事务)的运行,处理
TM相当于班长,负责监督整个班级(整个事务)的流程
RM相当于学生,负责正常的事务分支相关工作
2.AT模式工作机制
前提:
TM通知TC发起全局事务,TC生成全局事务id(xid)返回给TM,xid可以通过openfeign在微服务调用链中进行传递
一阶段提交(分支事务提交):
1、解析sql语句,生成前镜像和后镜像,然后将前镜像阿宁和后镜像绑定分支事务id,xid,记录到undo_log表(为了将来分支事务回滚)
2、分支事务提交(提交分支事务前必须获取全局锁)
3、将本地事务提交的结果上报给TC
分布式交易解决方案:
二阶段:
二阶段提交:
如果事务边界没有发生任何异常,全局事务可以提交,TM通知TC进行全局事务的提交,TC释放全局锁,RM删除undo_log记录
二阶段回滚:
如果事务边界发生任何异常,全局事务必须回滚,TM通知TC全局事务回滚,TC通知RM进行分支事务回滚,分支事务根据undo_log反向补偿(必须获取全局锁)
3.写隔离
一阶段本地事务提交前,需要确保先拿到 全局锁 。
拿不到 全局锁 ,不能提交本地事务。
拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
两个事务:tx1和tx2处理同一条行数据
tx1先执行,获得本地锁执行更新操作,获得全局锁,本地事务提交释放本地锁。
tx2在等待tx1释放本地锁时,获得本地锁,执行更新操作,请求获得全局行锁,由于全局锁被tx1占有,不断重试。
注意:
一阶段分支事务在提交本地事务前需要获取全局锁,获取本地锁后提交本地事务,然后就可直接释放本地锁
一阶段分支事务如果不能获取全局锁,则需要阻塞等待,直到获取全局锁才能提交本地事务;
事务持有的全局锁需要在二阶段全局事务提交或者回滚的时候才会释放
tx1 二阶段全局提交,释放全局锁 。tx2 拿到 全局锁 提交本地事务。
如果 tx1 的二阶段全局回滚,则 tx1 需要重新获取该数据的本地锁,进行反向补偿的更新操作,实现分支的回滚。
tx2占用本地锁,导致tx1请求本地锁,但无法获得,无法进行回滚
tx1占有全局锁,tx2请求全局锁,但无法获得,tx2不断重试直至请求超时,释放本地锁
此时,tx1获得本地锁,回滚事务,释放本地锁
4.读隔离
在数据库本地事务隔离级别 读已提交或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交 在select 语句后面加上for update(读取时需要获取全局锁,如不能获取需阻塞等待),实现全局读提交隔离级别。全局读未提交:tx2可直接读取数据:id=1 m=900
全局读提交:tx2读取数据时,首先获取本地锁,然后请求获取全局锁,此时全局锁被tx1持有,需要等待tx1释放才可读取数据
如果tx1提交,tx1释放全局锁,tx2获取到全局锁,读取结果:id=1 m=900
如果tx1回滚,tx1需要获取本地锁,此时本地锁被tx2持有,
tx2释放本地锁并重试,tx1获取到本地锁,事务回滚成功,释放本地锁、全局锁。
tx2随后获取本地锁、全局锁,读取结果:id=1 m=1000
https://blog.csdn.net/weixin_43931625/article/details/104387970
PS:先写这么多,后续在补充…