乐趣区

SpringBoot2-整合JTA组件多数据源事务管理

本文源码:GitHub·点这里 || GitEE·点这里

一、JTA 组件简介

1、JTA 基本概念

JTA 即 Java-Transaction-API,JTA 容许应用程序执行分布式事务处理,即在两个或多个网络计算机资源上拜访并且更新数据。JDBC 驱动程序对 JTA 的反对极大地加强了数据拜访能力。

XA 协定是数据库层面的一套分布式事务管理的标准,JTA 是 XA 协定在 Java 中的实现, 多个数据库或是音讯厂商实现 JTA 接口, 开发人员只须要调用 SpringJTA 接口即可实现 JTA 事务管理性能。

JTA 事务比 JDBC 事务更弱小。一个 JTA 事务能够有多个参与者,而一个 JDBC 事务则被限定在一个繁多的数据库连贯。下列任一个 Java 平台的组件都能够参加到一个 JTA 事务中

2、分布式事务

分布式事务(DistributedTransaction)包含事务管理器(TransactionManager)和一个或多个反对 XA 协定的资源管理器 (Resource Manager)。

资源管理器是任意类型的长久化数据存储容器,例如在开发中罕用的关系型数据库:MySQL,Oracle 等,消息中间件 RocketMQ、RabbitMQ 等。

事务管理器提供事务申明,事务资源管理,同步,事务上下文流传等性能,并且负责着所有事务参加单元者的互相通信的责任。JTA 标准定义了事务管理器与其余事务参与者交互的接口,其余的事务参与者与事务管理器进行交互。

二、SpringBoot 整合 JTA

我的项目整体结构图

1、外围依赖

<!--SpringBoot 外围依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--JTA 组件外围依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2、环境配置

这里 jtaManager 的配置,在日志输入中十分要害。

spring:
  jta:
    transaction-manager-id: jtaManager
  # 数据源配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    data01:
      driverClassName: com.mysql.jdbc.Driver
      dbUrl: jdbc:mysql://localhost:3306/data-one
      username: root
      password: 000000
    data02:
      driverClassName: com.mysql.jdbc.Driver
      dbUrl: jdbc:mysql://localhost:3306/data-two
      username: root
      password: 000000

3、外围容器

这里两个数据库连贯的配置手法都是一样的,能够在源码中自行下载浏览。基本思路都是把数据源交给 JTA 组件来对立治理,不便事务的通信。

数据源参数

@Component
@ConfigurationProperties(prefix = "spring.datasource.data01")
public class DruidOneParam {
    private String dbUrl;
    private String username;
    private String password;
    private String driverClassName;
}

JTA 组件配置

package com.jta.source.conifg;

@Configuration
@MapperScan(basePackages = {"com.jta.source.mapper.one"},sqlSessionTemplateRef = "data01SqlSessionTemplate")
public class DruidOneConfig {private static final Logger LOGGER = LoggerFactory.getLogger(DruidOneConfig.class) ;

    @Resource
    private DruidOneParam druidOneParam ;

    @Primary
    @Bean("dataSourceOne")
    public DataSource dataSourceOne () {

        // 设置数据库连贯
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setUrl(druidOneParam.getDbUrl());
        mysqlXADataSource.setUser(druidOneParam.getUsername());
        mysqlXADataSource.setPassword(druidOneParam.getPassword());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);

        // 事务管理器
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("dataSourceOne");
        return atomikosDataSourceBean;
    }

    @Primary
    @Bean(name = "sqlSessionFactoryOne")
    public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceOne") DataSource dataSourceOne) throws Exception{
        // 配置 Session 工厂
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSourceOne);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setMapperLocations(resolver.getResources("classpath*:/dataOneMapper/*.xml"));
        return sessionFactory.getObject();}

    @Primary
    @Bean(name = "data01SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryOne") SqlSessionFactory sqlSessionFactory) {
        // 配置 Session 模板
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

4、测试比照

这里通过两个办法测试后果做比照,在两个数据源之间进行数据操作时,只须要在接口办法加上 @Transactional 注解即可,这样保证数据在两个数据源间也能够保障一致性。

@Service
public class TransferServiceImpl implements TransferService {

    @Resource
    private UserAccount01Mapper userAccount01Mapper ;

    @Resource
    private UserAccount02Mapper userAccount02Mapper ;

    @Override
    public void transfer01() {userAccount01Mapper.transfer("jack",100);
        System.out.println("i="+1/0);
        userAccount02Mapper.transfer("tom",100);
    }

    @Transactional
    @Override
    public void transfer02() {userAccount01Mapper.transfer("jack",200);
        System.out.println("i="+1/0);
        userAccount02Mapper.transfer("tom",200);
    }
}

三、JTA 组件小结

在下面 JTA 实现多数据源的事务管理,应用形式还是绝对简略,通过两阶段的提交,能够同时治理多个数据源的事务。然而暴露出的问题也非常明显,就是比较严重的性能问题, 因为同时操作多个数据源, 如果其中一个数据源获取数据的工夫过长, 会导致整个申请都十分的长, 事务工夫太长, 锁数据的工夫就会太长,天然就会导致低性能和低吞吐量。

因而在理论开发过程中,对性能要求比拟高的零碎很少应用 JTA 组件做事务管理。作为一个轻量级的分布式事务解决方案,在小的零碎中还是值得举荐尝试的。

最初作为 Java 下的 API,原理和用法还是值得学习一下,开阔眼界和思路。

四、源代码地址

GitHub·地址
https://github.com/cicadasmile/middle-ware-parent
GitEE·地址
https://gitee.com/cicadasmile/middle-ware-parent

举荐浏览:SpringBoot 进阶系列

序号 文章题目
01 Boot2 整合 shard-jdbc 中间件,实现数据分库分表
02 Boot2 整合 JavaMail , 实现异步发送邮件性能
03 Boot2 整合 RocketMQ , 实现申请异步解决
04 Boot2 整合 Swagger2 , 构建接口治理界面
05 Boot2 整合 QuartJob , 实现定时器实时治理
06 Boot2 整合 Redis 集群 , 实现音讯队列场景
07 Boot2 整合 Dubbo 框架 , 实现 RPC 服务近程调用
08 Boot2 整合 ElasticSearch 框架, 实现高性能搜索引擎
09 Boot2 整合 JWT 框架, 解决 Token 跨域验证问题
10 Boot2 整合 FastDFS 中间件,实现文件散布治理
11 Boot2 整合 Shiro 框架,实现用户权限治理
12 Boot2 整合 Security 框架,实现用户权限治理
13 Boot2 整合 ClickHouse 数据库,实现数据高性能查问剖析
14 Boot2 整合 Drools 规定引擎,实现高效的业务规定
15 Boot2 整合 多数据源,配置 MybatisPlus 加强插件
16 Boot2 整合 Zookeeper 组件,治理架构中服务协调
17 Boot2 整合 Nacos 组件,环境搭建和入门案例详解
18 文件系统 (01):基于 Boot2 框架,治理 Excel 和 PDF
18 文件系统 (02):基于 Boot2 框架,治理 Xml 和 CSV
19 Boot2 整合 Kafka 组件,利用案例和流程详解
20 Boot2 整合 ElasticJob 框架,定制化治理流程
退出移动版