文章插图
如果是AT模式,这里调用的就是ATCore#branchSessionLock()
ATCore#branchSessionLock()检查是否拿到锁了
文章插图
文章插图
文章插图
文章插图
文章插图
文章插图
具体每种锁的实现就不往下看了,挑其中一个看下,就RedisLocker吧
文章插图
总之 , 分支注册的时候需要检查锁,拿到本次事务中所涉及的所有需要加锁的行的锁才能注册成功
所有行都加锁成功,分支注册才算成功,才会返回true
再回到AbstractCore#branchRegister(),整个方法是放在SessionHolder#lockAndExecute()中执行的
文章插图
文章插图
总结一下,分支注册:
- 创建一个BranchSession
- 加锁,获取所有行的锁
- 将BranchSession加到GlobalSession中
- 返回branchId
文章插图
分支注册,创建BranchSession,获取全局锁成功后将branchSession加入globalSession
3. 提交全局事务
文章插图
文章插图
首先判断全局事务状态是否为begin,如果不是则不应该提交 。如果是,则将事务active置为false,释放全局锁,判断是否可以异步提交 。分支类型是AT的都可以异步提交 , 因此AT模式,默认是异步提交 。如果不能异步提交,则采取同步提交 。
3.1. 同步提交
文章插图
文章插图
文章插图
遍历所有已注册的分支事务,向分支发送同步请求,告诉它全局事务开始提交了,不出意外的情况下返回分支状态是二阶段提交成功 。当所有分支都提交成功,则返回true,于是全局事务提交成功,返回全局事务状态为已提交 。如果有分支提交失败,则返回false,全局事务提交失败 , 返回全局状态为提交失败 。如果抛异常了,则会有定时任务稍后重试提交 。
3.2. 异步提交
文章插图
异步提交只是将全局状态置为异步提交中,剩下的事情交给定时任务去执行
启动的时候调用了DefaultCoordinator#init()方法,启动定时任务
文章插图
文章插图
每次 , 定时任务执行前,要先获取一把分布式锁,这个锁是io.seata.core.store.DistributedLocker , 不是分支注册时的那把锁io.seata.core.lock.Locker
文章插图
文章插图
异步提交首先将全局状态设置为AsyncCommitting,返回返回全局状态Committed 。后台有定时任务扫描,找到所有状态为AsyncCommitting的全局事务 , 循环遍历 。对于每个全局事务提交 , 调用DefaultCore#doGlobalCommit(),遍历所有已注册的分支事务,向分支事务发请求,通知其提交事务,分支事务返回二阶段提交成功,表示该分支事务提交成功,当所有分支事务都二阶段提交成功 , 则全局事务提交成功 。
文章插图
4. 回滚全局事务
文章插图
推荐阅读
- 观察者 CH58X/CH57X/V208 Observer例程讨论讲解
- Seata 1.5.2 源码学习
- Sql Server性能排查和优化懒人攻略
- 分布式事务框架 Seata 入门案例
- Azure DevOps Server 入门实践与安装部署
- 【Serverless】快速集成云函数HarmonyOS
- Eureka Server 实现在线扩容
- Seata 环境搭建
- 【Serverless】云函数微信小程序
- SpringCloud整合分布式事务Seata 1.4.1 支持微服务全局异常拦截