Seata源码分析

208 阅读4分钟

一 、Seata编译

1、进行编译

image.png

二、启动源码

1、启动

image.png

更改 注册中心 和配置中心都是nacos

image.png

2、找入口

image.png

从上面我们可以看出Seata1.5.2就是一个springboot项目,我们可以从自动装配的角度来看,我们看一下seata-spring-boot-starter.1.5.2.jar里面的spring.factories,里面有对应的自动装配类SeataAutoConfiguration

image.png

在SeataAutoConfiguration我们找到对应注入的类GlobalTransactionScanner,通过名称我们应该推算出,他应该是对应@GlobalTransaction进行扫描,然后注入到容器

image.png

我们看他的继承关系发现,他是一个后置处理器,并且他继承AbstractAutoProxyCreator 这里面应该是创建代理的,他创建代理类是不是在wrapIfNecessary这个方法里面创建的?,好那我们来看一下

image.png

2.1 创建代理类

image.png

image.png

2.2 初始化 关键组件 TM RM

实现接口InitializingBean我们需要看他的对应方法afterPropertiesSet,对TM RM进行初始化

image.png

image.png

TM 和RM的通信都是通过Netty通信

image.png

image.png

3、发送请求进如核心方法

image.png

调用的时候一定会调用到我们的拦截器GlobalTransactionalInterceptor.invoke方法

image.png

image.png

处理全局事务

image.png

image.png

image.png

4、开启全局事务

4.1 客户端源码

image.png

开启事务这里的全局事务的默认超时时间是60s

image.png

image.png

image.png

发送请求获取全局事务Id

发送同步请求

image.png

image.png

这里客户端是在GlobalTransactionScanner 实现了接口InitializingBean

4.2 服务端处理

image.png

服务端处理我们这里有个核心类DefaultCoordinator

协调者我们看一下接口就有事务的处理

image.png

开启全局事务:

image.png

持久话数据:

image.png

  • 获取全局事务Id

    image.png

    image.png

    image.png

  • 开启事务

    image.png

image.png

image.png

image.png

进行数据持久化 重要接口TransactionStoreManager

image.png

这里对应的持久化的策略

image.png

核心新增更新等操作

image.png

image.png

5、执行业务逻辑

5.1 客户端执行

本地事务提交:业务数据和undo.log落库

注册分支事务、增加对应的锁

image.png

我们想我们在创建数据源的时候创建一个代理数据源 DataSourceProxy, 通过DataSourceProxy 我们可以获取代理链接ConnectionProxy,通过代理链接我们可以获取PreparedStatementProxy,那我们执行sql应该是在这里

image.png

image.png

image.png

image.pngimage.png

image.png

image.png

image.png

image.png

key1: 设置手动提交

image.png

key2: 形成前后置镜像,这里的镜像执行形成,并没有插入数据库

image.png

key3:进行提交

这里面有commit和docommit,注册回滚等操作

image.png

image.png

image.png

image.png

key1: 注册分支事务

image.png

image.png

key2:插入日志

image.png

插入日志

image.png

image.png

image.png

上述插入日志但是并没有提交

5.2 服务端源码

注册分支事务、和分支锁

image.png

注册分支事务入口DefaultCoordinator

image.png

image.png

image.png

5.2.1获取全局事务

image.png

image.png

image.png

image.png

5.2.2、创建BranchSession

image.png

image.png

5.2.3、增加分支事务锁,防止数据被修改

image.png

image.png

image.png

行锁收集,为什么行锁是list,因为update的时候可能是多行

image.png

image.png

image.png

image.png

image.png

 img

5.2.4、向全局session中添加分支session

image.png

image.png

image.png

image.png

image.png

image.png

image.png

5.2.5、出现异常释放锁

image.png

image.png

image.png

image.png

image.png

image.png

5.2.6: 返回分支会话的分支ID

image.png

6、服务间传递xid

6.1 Feign 传递xid

image.png

执行方法时候获取Request

image.png

image.png

6.2 RestTemplate进行调用

ClientHttpRequestInterceptor

image.png

7、提交事务

image.png

7.1 客户端

image.png

image.png

image.png

image.png

7.2 服务端

image.png

7.2.1 事务提交将事务改为异步提交中状态

image.png

image.png

image.png

image.png

image.png

7.2.2 定时任务处理异步提交的全局事务

定时任务处理对应的提交数据,这里每一秒执行一次

image.png

image.png

获取全局事务的分支事务,删除undolog

image.png

根据删除的分支事务的undolog的状态来处理,处理分支事务的数据和分支事务锁

image.png

image.png

重点我们分析一下key4: 删除分支事务释放全局锁

image.png

image.png

image.png

image.png

image.png

image.png

删除全局事务

image.png

image.png

image.png

image.png

image.png

image.png

image.png

7.2.3 分支事务客户端删除undolog

image.png

image.png

image.png

image.png

image.png

异步处理

image.png

image.png

image.png

image.png

image.png

image.png

image.png

8、事务回滚

8.1 客户端

image.png

image.png

image.png

image.png

image.png

image.png

image.png

8.2 服务端

image.png

客户端发送的请求是GlobalRollbackReqeust,那我们再服务端进行全文搜索

image.png

image.png

image.png

image.png

key1:事务回滚,先通过全局事xid找到全局事务和分支事务 1.先通过全局事务XID找到去global_table查询到全局事务对象 2.通过查询出来的xid对象去查询branch_talbe是否有分支事务,最后将这两个事务对象封装到GlobalSession中 这里传入的true代表全局事务和分支事务都查询出来,全局事务是一条数据,分支事务可能会多条是一个list

image.pngimage.png

image.png

image.png

key2:真正的回滚逻辑

image.png

如果分支事务是在一阶段失败的,调用removeBranch,释放锁

image.png

image.png

image.png

image.png

image.png

branchRollback回滚分支事务,这里是server端,所以这里的分支事务的回滚是调用的远程进行回滚的而远程回滚就是使用的undo log日志表来回滚的

image.png

image.png

image.png、、

根据调用客户端删除undolog的返回状态,来判断怎样处理

image.png

最后定时任务删除回滚对应的全局事务

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

8.3 客户端进行回滚

image.png

上面我们知道回滚我们发送请求为BranchRollbackRequest,那我们来到客户端端来全文搜索

image.png

image.png

image.png

在这里的undo方法中,会生成回滚sql,执行,然后删除undolog日志

image.png

image.png

image.png

9、查看回滚日志信息

navicat中查看中选择文本

image.png