SpringBoot Atomikos 多數(shù)據(jù)源分布式事務(wù)

之前的 《spring 動(dòng)態(tài)切換获询、添加數(shù)據(jù)源實(shí)現(xiàn)以及源碼淺析》 中介紹了如何使用 spring 提供的 AbstractRoutingDataSource 配置多數(shù)據(jù)源,有了多數(shù)據(jù)源自然要管理事務(wù)的一致性仍翰。
上篇文章中提到過配置多數(shù)據(jù)源的兩種方式

  1. 使用AbstractRoutingDataSource
  2. 配置多個(gè) SqlSessionFactory

前言

閱讀了一下spring的源碼,由于 spring 事務(wù)的機(jī)制观话,在開啟事務(wù)之前spring 會(huì)去創(chuàng)建當(dāng)前數(shù)據(jù)源的 事務(wù)object予借,直到事務(wù)提交,spring 都不會(huì)在乎你是否切換了數(shù)據(jù)源频蛔。這就導(dǎo)致了灵迫,使用 AbstractRouting DataSource 方式開啟事務(wù)時(shí),切換數(shù)據(jù)源不生效晦溪。
關(guān)于如何解決這個(gè)問題瀑粥,感興趣的朋友可以去閱讀一下:http://www.reibang.com/p/61e8961c6154

本文只討論上述第二種方式結(jié)合 atomikos 管理多數(shù)據(jù)源事務(wù)。

Atomikos

來自:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html

Atomikos is a popular open source transaction manager which can be embedded into your Spring Boot application. You can use thespring-boot-starter-jta-atomikos Starter to pull in the appropriate Atomikos libraries. Spring Boot auto-configures Atomikos and ensures that appropriate depends-on settings are applied to your Spring beans for correct startup and shutdown ordering.

By default, Atomikos transaction logs are written to a transaction-logs directory in your application’s home directory (the directory in which your application jar file resides). You can customize the location of this directory by setting a spring.jta.log-dir property in your application.properties file. Properties starting with spring.jta.atomikos.properties can also be used to customize the Atomikos UserTransactionServiceImp. See the AtomikosProperties Javadoc for complete details.

引入spring-boot-starter-jta-atomikos三圆,spring boot 為我們自動(dòng)配置
Atomikos狞换,我們可以通過 spring.jta.xxx 修改默認(rèn)配置。

Talk is cheap. Show me the code

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
  • application.properties
#spring.jta.log-dir=classpath:tx-logs
spring.jta.transaction-manager-id=txManager

spring.datasource.druid.system-db.name=system-db
spring.datasource.druid.system-db.url=jdbc:mysql://localhost:3306/test1?useSSL=false
spring.datasource.druid.system-db.username=root
spring.datasource.druid.system-db.password=taven753
spring.datasource.druid.system-db.initialSize=5
spring.datasource.druid.system-db.minIdle=5
spring.datasource.druid.system-db.maxActive=20
spring.datasource.druid.system-db.maxWait=60000
spring.datasource.druid.system-db.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.system-db.minEvictableIdleTimeMillis=30000
spring.datasource.druid.system-db.validationQuery=SELECT 1
spring.datasource.druid.system-db.validationQueryTimeout=10000
spring.datasource.druid.system-db.testWhileIdle=true
spring.datasource.druid.system-db.testOnBorrow=false
spring.datasource.druid.system-db.testOnReturn=false
spring.datasource.druid.system-db.poolPreparedStatements=true
spring.datasource.druid.system-db.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.druid.system-db.filters=stat,wall
spring.datasource.druid.system-db.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.druid.system-db.useGlobalDataSourceStat=true

spring.datasource.druid.business-db.name=business-db
spring.datasource.druid.business-db.url=jdbc:mysql://localhost:3306/test2?useSSL=false
spring.datasource.druid.business-db.username=root
spring.datasource.druid.business-db.password=taven753
spring.datasource.druid.business-db.initialSize=5
spring.datasource.druid.business-db.minIdle=5
spring.datasource.druid.business-db.maxActive=20
spring.datasource.druid.business-db.maxWait=60000
spring.datasource.druid.business-db.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.business-db.minEvictableIdleTimeMillis=30000
spring.datasource.druid.business-db.validationQuery=SELECT 1
spring.datasource.druid.business-db.validationQueryTimeout=10000
spring.datasource.druid.business-db.testWhileIdle=true
spring.datasource.druid.business-db.testOnBorrow=false
spring.datasource.druid.business-db.testOnReturn=false
spring.datasource.druid.business-db.poolPreparedStatements=true
spring.datasource.druid.business-db.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.druid.business-db.filters=stat,wall
spring.datasource.druid.business-db.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.druid.business-db.useGlobalDataSourceStat=true
  • system 數(shù)據(jù)源的配置類
@Configuration
@MapperScan(basePackages = SystemDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "systemSqlSessionFactory")
public class SystemDataSourceConfig {

    static final String PACKAGE = "com.gitee.taven.mapper.system";
    
    @Autowired
    private SystemProperties systemProperties;

    @Bean(name = "systemDataSource")
    @Primary
    public DataSource systemDataSource() {
        AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
        ds.setXaProperties(PojoUtil.obj2Properties(systemProperties));
        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        ds.setUniqueResourceName("systemDataSource");
        ds.setPoolSize(5);
        ds.setTestQuery("SELECT 1");
        return ds;
    }

    @Bean
    @Primary
    public SqlSessionFactory systemSqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(systemDataSource());
        return sqlSessionFactoryBean.getObject();
    }
    
}
  • 更新于 2019.6.24舟肉,在簡友LT的幫助下修噪,發(fā)現(xiàn)了一個(gè)bug,由于MySQL的wait_timeout 機(jī)制度气,會(huì)導(dǎo)致數(shù)據(jù)庫連接在長時(shí)間未使用的情況(MySQL默認(rèn)是8小時(shí))下失效
    雖然我們配置了Druid的檢查機(jī)制割按,但是還要在AtomikosDataSourceBean 的屬性上添加一個(gè)屬性,如下:
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
// 省略
ds.setTestQuery("SELECT 1");
  • business 數(shù)據(jù)源的配置類同上
  • 省略了 mybatis 代碼磷籍,通過service 測試事務(wù)适荣,拋出異常后,事務(wù)會(huì)回滾
@Service
public class UserService {

    @Autowired private UsersMapper usersMapper;
    
    @Autowired private UserInformationsMapper userInformationsMapper;
    
    @Transactional
    public void testJTA() {
        Users u = new Users();
        u.setUsername("hmj");
        u.setPassword("hmjbest");
        usersMapper.insertSelective(u);
        
        UserInformations ui = new UserInformations();
        ui.setUserid(666l);
        ui.setEmail("dsb");
        userInformationsMapper.insertSelective(ui);
        
//      int i = 10/0;
    }
    
}

本文Demo

Github, Gitee

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末院领,一起剝皮案震驚了整個(gè)濱河市弛矛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌比然,老刑警劉巖丈氓,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異强法,居然都是意外死亡万俗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門饮怯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闰歪,“玉大人,你說我怎么就攤上這事蓖墅】馓龋” “怎么了临扮?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長教翩。 經(jīng)常有香客問我杆勇,道長,這世上最難降的妖魔是什么饱亿? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任蚜退,我火速辦了婚禮,結(jié)果婚禮上路捧,老公的妹妹穿的比我還像新娘关霸。我一直安慰自己传黄,他們只是感情好杰扫,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著膘掰,像睡著了一般章姓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上识埋,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天凡伊,我揣著相機(jī)與錄音,去河邊找鬼窒舟。 笑死系忙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惠豺。 我是一名探鬼主播银还,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洁墙!你這毒婦竟也來了蛹疯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤热监,失蹤者是張志新(化名)和其女友劉穎捺弦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體孝扛,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡列吼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苦始。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寞钥。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡氧急,死狀恐怖潮饱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情攒钳,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布香浩,位于F島的核電站类缤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏邻吭。R本人自食惡果不足惜餐弱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囱晴。 院中可真熱鬧膏蚓,春花似錦、人聲如沸畸写。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枯芬。三九已至论笔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間千所,已是汗流浹背狂魔。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留淫痰,地道東北人最楷。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像待错,于是被迫代替她去往敵國和親籽孙。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評論 6 342
  • 原文鏈接:https://docs.spring.io/spring-boot/docs/1.4.x/refere...
    pseudo_niaonao閱讀 4,677評論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理朗鸠,服務(wù)發(fā)現(xiàn)蚯撩,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • =========================================================...
    _燈火闌珊處閱讀 2,399評論 0 3
  • 今天出去玩了回來晚了 幸好作業(yè)量少啊 淺色的涂色就很尷尬了 鉛筆擦不干凈(><) 水果風(fēng) 么么噠 夏安(?????)
    很酷的豆子閱讀 138評論 1 1