Seata执行整体流程(AT模式)| Seata源码 - 自动配置数据库代理 | AT和XA的区别

Posted 做猪呢,最重要的是开森啦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Seata执行整体流程(AT模式)| Seata源码 - 自动配置数据库代理 | AT和XA的区别相关的知识,希望对你有一定的参考价值。

0. 相关术语:

  • TC一般指seata-server
  • TM一般就是事务操作接口入口的服务,也就是标注@GlobalTransactional的服务
  • RM一般就是涉及整体事务操作的服务
  • 比如确认订单加积分,订单服务就作为TM和RM,积分服务就作为RM

实验代码可见GitHub

1. 整体流程:

  1. TM、RM注册
  2. 初始化后置处理器方法中引入全局事务拦截器GlobalTransactionalInterceptor
  3. 请求时调用拦截器invoke方法,TM发起全局事务
  4. RM通过数据库代理执行本地事务
  • 解析SQL - 关闭自动提交 - 查询前镜像 - 执行业务SQL - 查询后镜像 - 根据前后镜像构建undo_log - 提交写入undo_log - 手动提交业务SQL
  1. TM发送commit/rollback给TC
  2. 分支事务提交/回滚:
  • 如果提交:采用异步线程去删除undo_log,一阶段已经提交本地事务了
  • 如果回滚:根据分支事务id和全局事务xid获取undo_log(数据库表有唯一索引),然后进行反向补偿,删除undo_log
1.1. TM、RM注册
  • 自动配置类SeataAutoConfiguration引入GlobalTransactionScanner
  • GlobalTransactionScanner实现InitializingBean,在IOC创建bean时,会调用afterPropertiesSet方法
  • 内部调用initClient方法中,进行TM、RM注册

1.2. 引入全局事务拦截器GlobalTransactionalInterceptor
  • GlobalTransactionScanner继承了AbstractAutoProxyCreator,是个后置处理器,并重写了wrapIfNecessary方法

  • 在IOC创建bean时,会调用postProcessAfterInitialization后置处理器方法,然后执行wrapIfNecessary
  • 引入全局事务拦截器GlobalTransactionalInterceptor

1.3. 请求时调用拦截器invoke方法,TM发起全局事务
  • 当发起请求,再调用Controller时会先调用拦截器,也就是全局事务拦截器GlobalTransactionalInterceptor的invoke()方法
  • 如果要发起全局事务就调用handleGlobalTransaction方法

  • 调用transactionalTemplate.execute方法,进行事务创建/加入,发起全局事务

beginTransaction是一个模板方法,tx.begin发起全局事务会生成和绑定全局事务xid

1.4. RM通过数据库代理执行本地事务:
  • beginTransactionf发起全局事务后,business.execute()最终反射调用@GlobalTransactional注解的方法
  • 当业务方法中进行数据库操作时,seata通过数据库代理执行
  • 解析SQL - 关闭自动提交 - 查询前镜像 - 执行业务SQL - 查询后镜像 - 根据前后镜像构建undo_log - 提交写入undo_log - 手动提交业务SQL

1.4 .1. 启用数据库自动代理:
  • 此处seata-all是1.4.2版本,需要在启动类加上@EnableAutoDataSourceProxy注解
  • 最终是会注册两个bean:SeataDataSourceBeanPostProcessor、SeataAutoDataSourceProxyCreator

  • bean创建SeataDataSourceBeanPostProcessor时,调用后置处理器方法进行数据源代理(DataSourceProxy)

  • 数据源获取Connection 的时候,也会对Connection 进行代理(ConnectionProxy):

  • 通过ConnectionProxy获取statement时(父类AbstractConnectionProxy方法),seata也对statement进行了代理;

1.4 .2. 数据源代理执行SQL:
  • seata对数据源到statement都进行了代理,当statement执行SQL时,最终调用ExecuteTemplate.execute核心方法

调用链:

  • executor.execute → io.seata.rm.datasource.exec.BaseTransactionalExecutor#doExecute → executeAutoCommitTrue
  • executeAutoCommitFalse(args) → connectionProxy.commit(); → doCommit → processGlobalTransactionCommit

执行流程:

  • 解析 SQL:得到 SQL 的类型、表、条件等相关的信息
  • 关闭自动提交
  • 查询前镜像(原始数据):根据解析得到的条件信息,生成查询语句,定位数据。
  • 执行业务 SQL
  • 查询后镜像(修改后数据):根据前镜像的结果,通过 主键 定位数据。
  • 构建undo_log日志
  • 提交写入undo_log日志
  • 手动提交业务SQL,本地事务也提交了,但全局事务没有


1.5 TM发送commit/rollback给TC:
  • RM执行完本地事务(也就是业务方法执行完),都执行正常TM就发送commit给TC,否则就rollback
  • 通过全局事务xid控制commit/rollback

1.7 分支事务提交/回滚:
  • 如果提交:采用异步线程去删除undo_log,一阶段已经提交本地事务了
  • 如果回滚:根据分支事务id和全局事务xid获取undo_log(数据库表有唯一索引),然后进行反向补偿,删除undo_log
  • 详情可以见参考链接:seata客户端二阶段分支事务的提交和回滚

2. AT和XA的区别:

 核心区别在于:

  • AT模式一阶段本地事务提交完后会提交本地事务;
  • XA模式要在所有的本地事务执行完成后,TC才发送指令让所有的RM提交事务、释放本地锁。
  • 所以XA的性能会低,但能保证强一致性效果

以上是关于Seata执行整体流程(AT模式)| Seata源码 - 自动配置数据库代理 | AT和XA的区别的主要内容,如果未能解决你的问题,请参考以下文章

分布式事务 - AT模式Dubbo集成Seata

分布式事务:Seata框架AT模式及TCC模式执行流程剖析

seata的AT模式调用流程分析

Seata中的四种不同的事务模式(XAATTCCSAGA)

Seata中的四种不同的事务模式(XAATTCCSAGA)

Seata分布式事务AT模式介绍