1. 程式人生 > 其它 >SpringBoot多資料來源中的分散式事務

SpringBoot多資料來源中的分散式事務

雖然現在微服務越來越流行,我們的系統隨之也拆分出來好多的模組功能。這樣做的目的其實就是為了彌補單體架構中存在的不足。隨著微服務的拆分,肯定設計到分庫分表,但這之中肯定設計到分散式事務。最典型的例子就是銀行轉賬,比如銀行A給銀行B轉賬500 塊錢,流程肯定是銀行A-500,銀行B+500,在這個過程要麼都成功,要麼都成仁。首先銀行A和銀行B的數肯定是在不同的資料庫,如果在轉賬的過程中,銀行A首先-500庫錢之後,在銀行B+500的時候出現了問題,如果事務不回滾,那麼就會出現500塊錢丟失的問題,也就是出現了事務一致性問題。

JTA + Atomikos解決分散式事務

一、JTA

JTA(java Transaction API)是JavaEE 13 個開發規範之一。Java 事務API,允許應用程式執行分散式事務處理——在兩個或多個網路計算機資源上訪問並且更新資料。JDBC驅動程式的JTA支援極大地增強了資料訪問能力。事務最簡單最直接的目的就是保證資料的有效性,資料的一致性。

二、Atomikos

Atomikos是一個為Java平臺提供增值服務的並且開源類事務管理器。

工作原理:分散式事務包括事務管理器和支援XA的資源管理器。資源管理器就是我們的DB,事務管理器就是承擔調節和控制所有參與DB所設計到的事務。

個人理解:Atomikos 獲取到資料庫的連線之後,會遮蔽資料庫底層的事務控制,然後全部交給 Atomikos,進行統一的排程和控制。

接下來,我們簡單的做一個基於 SpringBoot 的分散式事務控制。

1、首先我們要引入需要引入的maven庫

<!--分散式事務-->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jta-atomikos</artifactId>

</dependency>

2、配置資料來源

3、配置類

最主要的配置

@Configuration

@MapperScan(basePackages = "com.example.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")

public class DB1DataSourcesConfig {

@Primary

@Bean(name = "db1DataSource")

public DataSource dataSource(DB1Config DB1Config) {

// 設定資料庫連線

MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();

mysqlXADataSource.setUrl(DB1Config.getUrl_jdbc());

mysqlXADataSource.setUser(DB1Config.getUsername());

mysqlXADataSource.setPassword(DB1Config.getPassword());

mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);

// 交給事務管理器進行管理

AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();

atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);

atomikosDataSourceBean.setUniqueResourceName("db1DataSource");

return atomikosDataSourceBean;

}

@Primary

@Bean(name = "db1SqlSessionFactory")

public SqlSessionFactory sqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {

SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();

sessionFactoryBean.setDataSource(dataSource);

sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/db1/*.xml"));

org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();

configuration.setMapUnderscoreToCamelCase(true);

sessionFactoryBean.setConfiguration(configuration);

return sessionFactoryBean.getObject();

}

@Primary

@Bean(name = "db1SqlSessionTemplate")

public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {

return new SqlSessionTemplate(sqlSessionFactory);

}

}

這樣基本就配置完了,這裡我只寫了一個數據庫的配置,另外一個同這個一樣,就是資料庫資訊變了而已。

4、測試

這裡設計到兩個資料的修改,學生姓名和學生分數成績,這兩個資料分別儲存在不同的資料庫。我們通過介面先修改使用者資訊,接著再修改使用者的分數資訊。

沒有修改前的資料

我們先沒不加事務,先看下如果再修改分數的時候出現異常,使用者資訊會不會回滾回去。

結果

首先程式碼在39行報錯,如果按照我們的邏輯,如果修改分數失敗,那麼相應的使用者的年齡修改也是不成功的,但是結果顯示使用者的年齡還是被修改了,顯然這個介面並沒有被分散式事務所管理。

總結:以上就是 JTA + Atomikos 實現分散式事務的整個過程,相對實現功能來說還是比較簡單的,以上的測試是基於單個的 SpringBoot 專案的,相對於真正的微服務來說,這樣的方式我還沒有進行測試,如果需要進行微服務之間的事務管理,也可以通過 mq 或者 dubbo 去進行事務的一致性管理。