温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

什么是seata源码

发布时间:2021-09-29 15:52:12 来源:亿速云 阅读:80 作者:iii 栏目:大数据

本篇内容介绍了“什么是seata源码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

seata源码阅读笔记

  • 本文没有seata的使用方法,怎么使用seata可以参考官方示例,详细的很。

  • 本文基于v0.8.0版本,本文没贴代码。

  • seata中的三个重要部分:

    1. TC:事务协调器,维护全局事务和分支事务的状态,驱动全局提交或回滚,就是seata的服务端。

    2. TM:事务管理器,开始全局事务,提交或回滚全局事务。

    3. RM:资源管理器,管理正在处理的分支事务的资源,向TC注册并报告分支事务的状态,并驱动分支事务的提交或回滚。

seata的初始化

  1. TC启动

  2. RM发送jdbcUrl、applicationId和transactionServiceGroup三个参数向TC发起注册,建立连接。入口是在DataSourceProxy实例化的时候

  3. TM发送applicationId和transactionServiceGroup两个参数向TC发起注册,建立连接。

TM-处理全局事务

全局事务发起者,就是我们加@GlobalTransactional注解的方法,seata会代理我们的方法,通过以下步骤来完成全局事务。

  1. 发送全局事务开始请求到TC,TC返回xid(全局事务唯一id),将xid绑定到当前线程

  2. 执行我们的业务逻辑

  3. 业务逻辑成功,发送全局事务commit请求到TC,如果失败则重试

  4. 业务逻辑异常(可配置回滚规则,即哪些异常回滚),发送全局事务rollback请求到TC,如果失败则重试

  5. 清理资源,事务结束

源码阅读入口:io.seata.spring.annotation.GlobalTransactionalInterceptor#invoke

RM-处理分支事务

rm需要代理我们项目中的数据源,这一步需要我们修改自己的代码,如下:

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

    /**
     * 需要将DataSourceProxy 设置为主数据源,否则事务无法回滚
     */
    @Primary
    @Bean("dataSource")
    public DataSource dataSource(DataSource druidDataSource) {
        return new io.seata.rm.datasource.DataSourceProxy(druidDataSource);
    }

代理数据源的主要目的是代理数据库连接,这样就可以控制分支事务的commit、rollback。

seate的rm-datasoure模块中有这几个代理类DataSourceProxy、ConnectionProxy、StatementProxy,通过代理jdbc中的这几个类,让我们的sql通过ExecuteTemplate来进行执行,这个类就是我们了解seata怎么控制分支事务的入口。下面看分支事务的处理步骤:

  1. 将xid绑定到当前数据库连接(xid怎么来的?在后面)

  2. 拿到sql执行前数据库表中的数据记录beforeImage(只是受影响的数据及字段,通过解析我们的sql完成)

  3. 执行我们的业务sql

  4. 拿到sql执行后数据库表中的数据记录afterImage

  5. 用变动数据的主键值作为lockKey,并保存到当前数据库连接中

  6. 将beforeImage和afterImage转换成undo log,并保存到当前数据库连接中

  7. 向TC发送全局锁请求(带着xid和lockKey),TC返回branchId,表示拿到了全局锁,若不成功则重试(默认30次,每次间隔10ms);这个全局锁的是为了防止多个用户同时对同一数据进行修改,造成后面通过undo_log进行回滚操作时数据出错;这个锁在PhaseTwo完成后,TC会进行释放。

  8. 将undoLog保存到数据库的undo_log表中

  9. 提交数据库事务

  10. 向TC报告当前分支事务commit的结果(失败或成功),若报告不成功则重试(默认5次)

  11. commit成功后,清理当前数据库连接绑定的xid

  12. commit失败后,向上抛出异常,以便让tm知道,进行全局事务的回滚

这是PhaseOne的整个过程,下面看PhaseTwo:

  1. tc收到tm的全局事务提交或回滚请求后,会对这个全局事务中的所有分支事务进行通知,rm在收到通知后,进行回滚或者提交的操作

  2. 回滚:取出数据库undo_log进行数据补偿还原,成功后删除undo_log;提交:直接删除undo_log

  3. 返回tc处理结果

源码阅读入口: io.seata.rm.datasource.StatementProxy#execute

XID在服务链路中的传递

dubbo

用dubbo的filter实现的,源码:io.seata.integration.dubbo.TransactionPropagationFilter

原理就是:上游在filter中把xid放到RpcContext中,下游再从RpcContext拿到xid。

RestTemplate和Feign

对RestTemplate和Feign的支持不在seata-all中,而是在spring-cloud-alibaba-seata中

源码入口:

com.alibaba.cloud.seata.rest.SeataRestTemplateAutoConfiguration
com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration
com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration

原理就是:上游通过拦截器将xid放到请求的header中,下游通过拦截器从header中拿到xid。

seata还支持很多RPC框架,如sofa-rpc、motan等。我们也可以通过类似的方法使seata支持我们自己的rpc框架。

GlobalLock注解

如果是用 GlobalLock 修饰的本地业务方法,虽然该方法并非某个全局事务下的分支事务,但是它对数据资源的操作也需要先查询全局锁,如果存在其他 Seata 全局事务正在修改,则该方法也需等待。所以,如果想要Seata 全局事务执行期间,数据库不会被其他事务修改,则该方法需要强制添加 GlobalLock 注解,来将其纳入 Seata 分布式事务的管理范围。

功能有点类似于 Spring 的 @Transactional 注解,如果你希望开启事务,那么必须添加该注解,如果你没有添加那么事务功能自然不生效,业务可能出 BUG;Seata 也一样,如果你希望某个不在全局事务下的 SQL 操作不影响 AT 分布式事务,那么必须添加 GlobalLock 注解。

TC的高可用设计

seata服务端支持zk、nacos、eureka等作为服务发现,通过数据库实现数据共享,全局事务Session信息、分支事务Session信息,全局锁信息都是放在数据库中

TCC模式

TCC和AT的不同主要体现在RM这边,TC和TM都是一样的。

TCC的RM不会代理我们的数据源了,而是由我们自己指定rollback和commit逻辑,在二阶段中,TM在发起全局事务提交回滚时,RM只需要执行我们指定的rollback和commit方法就行了。

这种模式就是我们业务代码的变动要多些,效率是要比AT模式高些。

RM一阶段源码入口:io.seata.spring.tcc.TccActionInterceptor#invoke

RM二阶段源码入口:io.seata.rm.tcc.TCCResourceManager#branchCommit#branchRollback

“什么是seata源码”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI