Seata原理与实现详解

Seata介绍

seata具体介绍可以查看官网描述,这里不做过多赘述。从开发人员角度可以理解为一套中间件,以@GlobalTranscation注解的方式替换掉原本只能支持单数据库,服务器的@Transcation实现多服务,多数据库的总体事务控制。
Seata官方文档

Seata配置和使用方式

参考我的另一篇文章consul集成seata配置

Seata客户端

组成部分

SeataAutoConfiguration 启动和注册等

客户端启动入口位置,注册组件

@ComponentScan(basePackages = "io.seata.spring.boot.autoconfigure.properties")
@ConditionalOnProperty(prefix = SEATA_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
@Configuration
@EnableConfigurationProperties({
    
    SeataProperties.class})

注册GlobalTransCationScaner组件

 @Bean
    @DependsOn({
    
    BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER, BEAN_NAME_FAILURE_HANDLER})
    @ConditionalOnMissingBean(GlobalTransactionScanner.class)
    public GlobalTransactionScanner globalTransactionScanner(SeataProperties seataProperties, FailureHandler failureHandler) {
    
    
        if (LOGGER.isInfoEnabled()) {
    
    
            LOGGER.info("Automatically configure Seata");
        }
        return new GlobalTransactionScanner(seataProperties.getApplicationId(), seataProperties.getTxServiceGroup(), failureHandler);
    }

GlobalTranscationScanner(@GlobalTranscation)

负责扫描GlobalTranscation注解是否存在,若存在且配置项支持全局事务控制,io.seata.spring.annotation.GlobalTransactionScanner#existsAnnotation ,存在则注册TM和RM客户端

@Override
    public void afterPropertiesSet() {
    
    
        ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
            (ConfigurationChangeListener)this);
        if (disableGlobalTransaction) {
    
    
            if (LOGGER.isInfoEnabled()) {
    
    
                LOGGER.info("Global transaction is disabled.");
            }
            return;
        }
        if (initialized.compareAndSet(false, true)) {
    
    
            initClient();
        }
    }

在initClient中,注册tm客户端,rm客户端 ,再注册一个sping注销事件,注销时停止rm和tm客户端远程实例

private void registerSpringShutdownHook() {
    
    
        if (applicationContext instanceof ConfigurableApplicationContext) {
    
    
            ((ConfigurableApplicationContext) applicationContext).registerShutdownHook();
            ShutdownHook.removeRuntimeShutdownHook();
        }
        ShutdownHook.getInstance().addDisposable(TmNettyRemotingClient.getInstance(applicationId, txServiceGroup));
        ShutdownHook.getInstance().addDisposable(RmNettyRemotingClient.getInstance(applicationId, txServiceGroup));
    }

TMClient.init()

TM客户端初始化,tm是事务发起和结束的基础,负责事务的开始和提交或回滚决定,注册时传入事务分组id
TM初始化完成的事情:
TmNettyRemotingClient.init()

  1. 注册处理器和注册心跳监测 io.seata.core.rpc.netty.TmNettyRemotingClient#registerProcessor
  2. 启动线程接收池 io.seata.core.rpc.netty.AbstractNettyRemotingClient#init
  3. 启动线程清理超时请求 io.seata.core.rpc.netty.AbstractNettyRemoting#init
    后续的处理在1中的processor中处理 io.seata.core.rpc.processor.client.ClientOnResponseProcessor#process,后续处理逻辑为消息发送

RMClient.init()

初始化方法:io.seata.core.rpc.netty.RmNettyRemotingClient#init
RM与TM的init中,都继承和调用了父类的init方法,所以这里一致io.seata.core.rpc.netty.AbstractNettyRemotingClient#init,启动线程接收池,启动线程清理超时请求
不同的是在注册processor的时候有些不一致:io.seata.core.rpc.netty.RmNettyRemotingClient#registerProcessor
注册提交处理器:RmBranchCommitProcessor
回滚处理器:RmBranchRollbackProcessor
undoLog处理器:RmUndoLogProcessor
TC响应处理器:ClientOnResponseProcessor
注册心跳监听

GlobalTransactionalInterceptor.invoke() 实际业务处理逻辑

实现org.aopalliance.intercept.MethodInterceptor io.seata.config.ConfigurationChangeListener
seata类配置改变和springmethod请求都会调用到io.seata.spring.annotation.GlobalTransactionalInterceptor#invoke方法,在其中判断方法体上是否有GlobalTransactional或者GlobalLock注解,然后决定是否处理全局事务

boolean localDisable = disable || (degradeCheck && degradeNum >= degradeCheckAllowTimes);
            if (!localDisable) {
    
    
                if (globalTransactionalAnnotation != null) {
    
    
                    return handleGlobalTransaction(methodInvocation, globalTransactionalAnnotation);
                } else if (globalLockAnnotation != null) {
    
    
                    return handleGlobalLock(methodInvocation, globalLockAnnotation);
                }
            }

handleGlobalTransaction中,实际处理方法为transactionalTemplate.execute,他是调用io.seata.tm.api.TransactionalTemplate#execute,并实io.seata.tm.api.TransactionalExecutor接口中定义的事务定义

TransactionalTemplate#execute

io.seata.tm.api.TransactionalTemplate#execute为TM中事务控制的主要逻辑位置
其中的逻辑为:

  1. getTranscationInfo,为外部global中定义的事务信息传入进来的
  2. 获取当前事务的XID,定义为事务参与者
  3. 获取1中事务(@GlobalTranscation)的传播类型,默认为REQUIRED
  4. 如果2中当前事务为空,则定义一个新全局事务
  5. 用4中的事务(之前的分支事务或者新全局事务)更新全局锁信息
  6. 如果4中创建的是一个新的全局事务,则提交请求给TC,声明一个新的全局事务。否则则自身为分支事务,不进行任何处理
  7. 处理1中注解编辑的正常业务
  8. 若捕捉到异常,处理回滚或异常信息
  9. 否则一切正常进行,则提交事务
  10. 清除事务信息,清空全局锁信息
  11. 若事务为暂停的, 在finally中重新唤醒

8中,回滚的异常处理逻辑在io.seata.tm.api.TransactionalTemplate#completeTransactionAfterThrowing
其中会判断用户定义是否需要回滚,若此处需要回滚则发送消息给TC,TC决定回滚并分发给RM,拥有相同XID的RM执行UndoLog中的数据恢复工作
9 中清除UndoLog信息

TccActionInterceptor

处理TCC模式下的截断和实现

Seata服务端

包组成部分

compressor

压缩机,提供7z,zip等格式的压缩

config

配置加载模块,包括Seata自身的配置和注册中心的配置信息

server

主启动模块,`io.seata.server.Server#main``为服务端的启动方法,其中也包含auth,log等模块,其中主要区别有io.seata.server.coordinator,coordinator为TC的主要逻辑处理协调类,负责事务回滚和提交的决策
启动步骤:

  • 获取服务端口并记录,加载日志文件,判断是否在容器中运行
  • 注册参数解析器
  • 注册metrics监控
  • 设置一些基本的系统属性
  • 初始化netty服务
  • 启动默认的coordinator(TC)
    - io.seata.server.coordinator.DefaultCoordinator#doGlobalBegin 决策事务开始,生成全局Xid并放入响应中
    - io.seata.server.coordinator.DefaultCoordinator#doGlobalCommit 全局提交
    - io.seata.server.coordinator.DefaultCoordinator#doGlobalRollback 全局回滚。
    此处都是TC发送消息给RM,所以其他全局方法不再一一列举
  • 注册系统注销处理
  • 启动远程nettyRemotingServer初始化
    注册各类处理器:
    - request message processor
    - response message processor:ServerOnResponseProcessor 负责处理commit和rollback
    - rm message processor :RegRmProcessor rm消息处理响应
    - tm message processor:RegTmProcessor tm消息处理响应
    - heartbeat message processor:ServerHeartbeatProcessor 客户端探知的心跳响应
  • 启动线程控制超时和消息池等(同客户端)

core

核心模块,包括登录认证,解压压缩,常量信息,事件,上下文,异常,锁,日志,调用,序列化,存储等功能的实现和封装

discovery

服务注册,负责注册到注册中心,其中分不同注册中心,方式不一致

metrics

metrics监控,为阿里的监控模块,低侵入集成

sqlparser

sql解析器,负责解析业务系统的sql和生成反向sql,是rm可以实现undo的主要解析

rm

rm处理器模块代码,RM为资源管理器,其代理数据库的提交和回滚,日志等操作
其中,rm-datasource 包处理数据库中的事务提交回滚等实现
rm-datasource包组成:

  • JDBC Proxy 代理类结构举例:

在这里插入图片描述

exec:对sql按照不同的sql类型进行执行,并保存执行前后镜像文件到undo数据结构中,用于事务回滚,继承结构举例
在这里插入图片描述

  • undoLog
    全局事务回滚、提交
    io.seata.rm.datasource.ConnectionProxy#processGlobalTransactionCommit 提交
    回滚
    @Override
    public void rollback() throws SQLException {
    
    
        targetConnection.rollback();//本地事务进行回滚
        if (context.inGlobalTransaction() && context.isBranchRegistered()) {
    
     
        // 如果是全局事务,且进行过分支注册,则向server报告未提交完成
            report(false);
        }
        context.reset();
    }

tm

事务管理器模块,事务的发起和结束(提交或回滚)由其处理和发送给tc

tcc

TCC模式的处理模块,TCC模式为TC决定是否提交和回滚,由RM提交确认状态,TC统一决定是否提交或回滚

saga

Saga模式的处理模块,Saga模式为支持降级处理策略的AT,其中降级算法由业务代码提供

integration

整合,一体化模块,其中集成dubbo和http客户端等

script

数据库脚本包,包含各个数据库的初始化脚本和其他数据库脚本等

springBootStarter

Seata客户端依赖包的自动装配类和扫描类等位于此包中

猜你喜欢

转载自blog.csdn.net/gsh6022/article/details/110870652