天天看點

JTA+Atomikos解決分布式事務問題

JTA分布式事務:Java Transaction API,允許應用程式執行分布式事務處理。

Atomikos:為java平台提供增值服務并且開源的事務管理器。

基于xa協定,xa協定是以兩階段送出協定為基礎的。

這種處理方案一般是針對傳統架構項目的分布式事務,不适合用在微服務架構中。

下面是springboot配置多個oracle資料源,重制分布式事務問題的例子

一、添加依賴

<dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>
        <!-- 這裡使用的是JPA包,也可使用JDBC包進行 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
           

由于maven倉庫沒有ojdbc6,需要自行下載下傳安裝

二、修改application.yml配置檔案

spring:
  jpa:
    database: oracle
    show-sql: true
  datasource:
    master:
      jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: oracle.jdbc.driver.OracleDriver
      username: wx
      password: 123
    slave1:
      jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: oracle.jdbc.driver.OracleDriver
      username: wl
      password: 123456
           

三、建立資料源配置檔案

@Configuration
public class DataSourceConfig {

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource dataSource1(){
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave1")
    public DataSource dataSource2(){
        return DataSourceBuilder.create().build();
    }
}
           

@Primary注釋表示這個資料源是預設資料源,如果沒有這個注釋的話,開啟事務的時候會報錯

四、建立JdbcTemplate配置類

@Configuration
public class JdbcTemplateConfig {

    @Bean
    public JdbcTemplate template1(@Qualifier("dataSource1")DataSource dataSource1){
        return new JdbcTemplate(dataSource1);
    }

    @Bean
    public JdbcTemplate template2(@Qualifier("dataSource2")DataSource dataSource2){
        return new JdbcTemplate(dataSource2);
    }
}
           

五、使用測試類進行測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class JtaatomikosApplicationTests {
    @Autowired
    private JdbcTemplate template1;
    @Autowired
    private JdbcTemplate template2;

    @Test
    @Transactional
    public void contextLoads() {
        String sql = "INSERT INTO \"test\" VALUES('asd','張三','24')";
        template1.update(sql);
        template2.update(sql);
        int i = 1/0;
    }

}
           

test表隻有三個字段:id,name,age

表裡邊資料都是空的。

執行測試方法contextLoads

控制台會抛異常

JTA+Atomikos解決分布式事務問題

此時去資料庫檢視資料會發現

JTA+Atomikos解決分布式事務問題

WL資料庫插入資料成功了。

JTA+Atomikos解決分布式事務問題

WX資料庫插入資料失敗了。

WX資料庫是主資料源,說明主資料源事務復原成功了,但是副資料源事務沒有復原,這就是分布式事務問題。

為了解決這個問題,我們引入atomikos解決

在原來的項目基礎上,添加依賴

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>
           

修改資料源配置檔案

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource1(){
        Properties properties = new Properties();
        properties.setProperty("URL","jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
        properties.setProperty("user","wx");
        properties.setProperty("password","123");
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaProperties(properties);
        atomikosDataSourceBean.setUniqueResourceName("dataSource1");
        atomikosDataSourceBean.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource");
        return atomikosDataSourceBean;
    }

    @Bean
    public DataSource dataSource2(){
        Properties properties = new Properties();
        properties.setProperty("URL","jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
        properties.setProperty("user","wl");
        properties.setProperty("password","123456");
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaProperties(properties);
        atomikosDataSourceBean.setUniqueResourceName("dataSource2");
        atomikosDataSourceBean.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource");
        return atomikosDataSourceBean;
    }
}
           

可以發現,我們去掉了@Primary和@ConfigurationProperties注釋,手動設定資料庫參數,将資料源類型改成了AtomikoDataSourceBean類型,這個類型的資料源需要添加XADataSource類型的資料源參數,這裡我們添加的是OracleXADataSource,這個類就是JTA類型的。

現在我們就已經把事務交給引入進來的全局事務協調了。

執行測試方法contextLoads

可以發現控制台同樣抛出/ by zero異常,WX和WL資料庫都沒有插入資料,說明都進行事務復原了。

繼續閱讀