SpringBoot2 整合JTA組件,多數據源事務管理

本文源碼:GitHub·點這裏 || GitEE·點這裏java

1、JTA組件簡介

一、JTA基本概念

JTA即Java-Transaction-API,JTA容許應用程序執行分佈式事務處理,即在兩個或多個網絡計算機資源上訪問而且更新數據。JDBC驅動程序對JTA的支持極大地加強了數據訪問能力。mysql

XA協議是數據庫層面的一套分佈式事務管理的規範,JTA是XA協議在Java中的實現,多個數據庫或是消息廠商實現JTA接口,開發人員只須要調用SpringJTA接口便可實現JTA事務管理功能。git

JTA事務比JDBC事務更強大。一個JTA事務能夠有多個參與者,而一個JDBC事務則被限定在一個單一的數據庫鏈接。下列任一個Java平臺的組件均可以參與到一個JTA事務中github

二、分佈式事務

分佈式事務(DistributedTransaction)包括事務管理器(TransactionManager)和一個或多個支持 XA 協議的資源管理器 ( Resource Manager )。web

資源管理器是任意類型的持久化數據存儲容器,例如在開發中經常使用的關係型數據庫:MySQL,Oracle等,消息中間件RocketMQ、RabbitMQ等。spring

事務管理器提供事務聲明,事務資源管理,同步,事務上下文傳播等功能,而且負責着全部事務參與單元者的相互通信的責任。JTA規範定義了事務管理器與其餘事務參與者交互的接口,其餘的事務參與者與事務管理器進行交互。sql

2、SpringBoot整合JTA

項目總體結構圖數據庫

SpringBoot2 整合JTA組件,多數據源事務管理

一、核心依賴

<!--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>

二、環境配置

這裏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

三、核心容器

這裏兩個數據庫鏈接的配置手法都是同樣的,能夠在源碼中自行下載閱讀。基本思路都是把數據源交給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);
    }
}

四、測試對比

這裏經過兩個方法測試結果作對比,在兩個數據源之間進行數據操做時,只須要在接口方法加上@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);
    }
}

3、JTA組件小結

在上面JTA實現多數據源的事務管理,使用方式仍是相對簡單,經過兩階段的提交,能夠同時管理多個數據源的事務。可是暴露出的問題也很是明顯,就是比較嚴重的性能問題,因爲同時操做多個數據源,若是其中一個數據源獲取數據的時間過長,會致使整個請求都很是的長,事務時間太長,鎖數據的時間就會太長,天然就會致使低性能和低吞吐量。

所以在實際開發過程當中,對性能要求比較高的系統不多使用JTA組件作事務管理。做爲一個輕量級的分佈式事務解決方案,在小的系統中仍是值得推薦嘗試的。

最後做爲Java下的API,原理和用法仍是值得學習一下,開闊眼界和思路。

4、源代碼地址

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

SpringBoot2 整合JTA組件,多數據源事務管理

推薦閱讀: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框架,定製化管理流程
相關文章
相關標籤/搜索