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庫

 

[AppleScript] 純文本查看 復制代碼
?
1
2
3
4
5
< font style = "color:rgb(77, 77, 77)" > < font face = "&quot" > < font style = "font-size:16px" > < ! --分布式事務-->
< dependency >
   < groupId > org.springframework.boot < / groupId >
   < artifactId > spring - boot - starter - jta - atomikos < / artifactId >
< / dependency > < / font > < / font > < / font >

 

2、配置數據源

3、配置類

最主要的配置

 

[AppleScript] 純文本查看 復制代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
< font style = "color:rgb(77, 77, 77)" > < font face = "&quot" > < font style = "font-size:16px" > @Configuration
@MapperScan ( basePackages = "com.example.mapper.db1" , sqlSessionFactoryRef = "db1SqlSessionFactory" )
public class DB 1 DataSourcesConfig {
  
     @Primary
     @Bean ( name = "db1DataSource" )
     public DataSource dataSource ( DB 1 Config DB 1 Config ) {
  
         / / 設置數據庫連接
         MysqlXADataSource mysqlXADataSource = new MysqlXADataSource ( ) ;
         mysqlXADataSource.setUrl ( DB 1 Config.getUrl_jdbc ( ) ) ;
         mysqlXADataSource.setUser ( DB 1 Config.getUsername ( ) ) ;
         mysqlXADataSource.setPassword ( DB 1 Config.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 ) ;
     }
} < / font > < / font > < / font >

 

這樣基本就配置完了,這里我只寫了一個數據庫的配置,另外一個同這個一樣,就是數據庫信息變了而已。

4、測試

這里設計到兩個數據的修改,學生姓名和學生分數成績,這兩個數據分別存儲在不同的數據庫。我們通過接口先修改用戶信息,接着再修改用戶的分數信息。

 

沒有修改前的數據

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

結果

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

我們先把數據改回原來,然后我們再把事務加上,看還不會出現這種問題。(方法上加@Transactional注解即可)

結果

加了分布式事務之后,通過結果就可以看到,如果后面的結果出現了錯誤,前面的數據也是會進行回滾的,保證了事務的前后一致性,確保了數據的安全准確。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM