全局事务服务GTS已进入下线状态,将于2023年7月20日全面停止支持。本文介绍如何将GTS迁移至开源项目Seata以承接分布式事务的需求。

前提条件

安装Seata

迁移方案

Seata于2019年1月正式开源,提供了涵盖多种事务模式的一站式分布式事务解决方案,符合技术演进的方向。由于目前开源Seata尚未提供对GTS Client的完全支持,因此在开发侧需要参考下文完成GTS到开源Seata的过渡。

说明 GTS只提供Java栈的支持,因此本文介绍的方案仅限于Java应用。

依赖迁移

迁移前GTS依赖如下所示。

       <dependency>
            <groupId>com.taobao.txc</groupId>
            <artifactId>txc-client</artifactId>
            <version>${gts.sdk.version}</version>
        </dependency>
        <dependency>
            <groupId>com.taobao.txc</groupId>
            <artifactId>txc-client-springcloud</artifactId>
            <version>${gts.sdk.version}</version>
        </dependency>

迁移后Seata依赖如下所示。

        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>${seata.version}</version>
        </dependency>
说明 seata.version建议使用1.5.2版本。

配置迁移

迁移前GTS配置如下。

spring.cloud.txc.txcAppName=sc_demo_business

# - txcServerGroup: spring.cloud.txc.txcServerGroup事务分组。
# txc_test_public.1129361738553704.QD 是公网测试的专用事务分组。
# 在阿里云环境运行时,请使用自己在官网开通的事务分组(GTS实例)。
spring.cloud.txc.txcServerGroup=default

# - mode: spring.cloud.txc.mode工作模式。
# AT=1,MT=2,不配置,则默认为1。
# spring.cloud.txc.mode=1

# - url: spring.cloud.txc.url服务发现地址。
# 本地公网测试的服务发现地址,配置如下。
# 在阿里云环境运行时,有默认地址,请删除该配置。
# spring.cloud.txc.url=https://test-cs-gts.aliyuncs.com

# 下面两个配置对应TxcTransactionScaner的accessKey/secretKey两个属性。
# 在阿里云环境运行时,请配置拥有spring.cloud.txc.txcServerGroup指定的事务分组(GTS实例)运行权限的用户的AK/SK。
# 本地公网测试不需要该配置。
#spring.cloud.txc.accessKey=xxxxxxxxx's AK
#spring.cloud.txc.secretKey=xxxxxxxxx's SK

迁移后Seata配置如下所示。

seata.application-id=seata-test
seata.tx-service-group=xxx
seata.registry.type=nacos
seata.registry.nacos.server-addr=xxx
seata.registry.nacos.group=xxx
seata.config.type=nacos
seata.config.nacos.server-addr=xxx
seata.config.nacos.group=seata-xxx

API迁移

常用API映射如下表所示。一般推荐只使用注解方式开启事务(@TxcTransaction/@GlobalTransaction),复杂场景业务可能会使用API手动控制事务。

对比项 GTS Seata
创建事务(注解) @TxcTransaction @GlobalTransaction
创建事务(API) TxcTransaction.getInstance(String vgroup, String ak, String sk) GlobalTransactionContext.getCurrentOrCreate()
获取事务XID TxcContext.getCurrentXid() RootContext.getXID()
事务挂起 TxcContext.suspendTxcTransaction() GlobalTransaction.suspend()
事务恢复 TxcContext.resumeTxcTransaction(String xid) GlobalTransaction.resume(SuspendedResourcesHolder suspendedResourcesHolder)
事务上下文绑定 TxcContext.bind(String xid, String nextSvrAddr) RootContext.bind(String xid)
事务上下文清除 TxcContext.unbind() RootContext.unbind()
TM初始化 无需 TMClient.init(String applicationId, String transactionServiceGroup)
RM初始化 无需 RMClient.init(String applicationId, String transactionServiceGroup)
开启事务 TxcTransaction.begin(long timeout) RootContext.unbind()
二阶段提交事务 TxcTransaction.commit() GlobalTransaction.commit()
二阶段回滚事务 TxcTransaction.rollback() GlobalTransaction.rollback()

AT事务模式

AT模式是通过代理数据源来完成JDBC的增强,如下表所示。

对比项 GTS Seata
代理数据源 TxcDataSource DatasourceProxy

GTS使用代理数据源需要业务手动组装,方法如下所示。

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

    @Bean("dataSourceProxy")
    public TxcDataSource dataSourceProxy(DruidDataSource dataSource) {
        return new TxcDataSource(dataSource);
    }

切换到Seata后,具体会分为3种用法。

  • 仅依赖seata-all,将上述代码中的TxcDataSource替换为DatasourceProxy
  • 仅依赖seata-all,去掉dataSourceProxybean逻辑,加入@EnableAutoDataSourceProxy注解。
  • 依赖seata-spring-boot-starter,去掉dataSourceProxybean逻辑, seata-spring-boot-starter会将Datasource接口自动代理为DatasourceProxy,无需额外处理。
其他情况

早期GTS与PolarDB-X(DRDS) 5.2以下版本存在集成关系。建议您将DRDS升级至5.3.x+版本。在 5.3版本中,Txc-client集成在DRDS-SERVER中,DRDS通过内部XA模式实现了分库分表的数据一致性。

按照如下方法,判断DRDS是否开启了GTS事务。

连接DRDS-Server,GTS按照库粒度开启,在对应数据库中执行以下SQL。

set autocomit=false;
select last_txc_xid();
commit;
set autocomit=tue;

若执行select last_txc_xid();的返回中包含8091,则可以使用GTS来解决DRDS内部的分库分表事务。您还需要升级DRDS版本来替代GTS事务,在此过程中需要注意灰度。

GTS可以处理分库分表事务,若还要处理涉及到跨服务的事务,需要配合Seata一起改造。目前Seata对于DRDS数据库未深度适配,可能存在性能问题。

TCC事务模式

TCC模式仅支持注解的模式使用,除使用@TxcTransaction/@GlobalTransaction创建事务外,还需要额外的API标注分支事务。

对比项 GTS Seata
分支事务 @MtBranch @TwoPhaseBusinessAction