spring多数据源分布式事务的分析与解决方案
一、概述
1、业务背景
对老系统进行重构合并,导致新系统需要同时对3个数据库进行管理。由于出现跨库业务,需要实现分布式事务。
2、开发环境
spring框架版本 4.3.10.RELEASE
持久层为结合mybatis写的领域模型,如

每一个entity对应数据库的一张表,@DataSource注解(自定义)了对应数据源的key值。所以一个业务中可能存在数据源的切换。
事务采用注解@Transaction驱动。
二、spring对多数据源的支持
spring框架通过抽象类AbstractRoutingDataSource来实现多数据源支持。
AbstractRoutingDataSource中有一个抽象方法determineCurrentLookupKey()。子类实现该方法即可。
举例如下:
package com.cmcc.cq.xx.common.mybatis;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return getDataSourceType();
}
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDataSourceType(String dataSourceType){
contextHolder.set(dataSourceType);
}
public static String getDataSourceType(){
return contextHolder.get();
}
public static void clearDataSourceType(){
contextHolder.remove();
}
}
ThreadLocal保存当前线程的数据源,执行数据库操作之前会通过解析注解@DataSource设置下次操作的数据源类型,即相应的key值(见后文数据源配置)。

到此,在不使用事务的情况下,可以完成多数据源切换。
三、spring分布式事务支持
1、DataSourceTransactionManager不支持多数据源
DataSourceTransactionManager事务管理器是一个单数据源事务管理器,在实例化时候会注入一个数据源。
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource">
</property>
</bean>
注意:虽然我们注入的是一个动态数据源,但是DataSourceTransactionManager不会因为我们使用动态数据源而跟着变化。
因为DataSourceTransactionManager开始事务时获取数据库connection时并不是每次都通过dataSource来获取,一般都是通过ConnectionHolder类获得。

所以开启事务会报找不到表或视图的异常。
同时DataSourceTransactionManager也不能实现跨库事务的一致性。
2、JtaTransactionManager支持分布式事务
JtaTransactionManager事务管理器只是提供一个接入方式,并没有做相应的实现,目前比较流行的分布式事务第三方实现是atomikos和jotm。其中jotm更新日期是2010年,建议使用atomikos。
两者配置也是大同小异,以atomikos为例。
引入maven依赖
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>3.7.0</version>
</dependency>
首先是数据源的配置,必须要使用类com.atomikos.jdbc.AtomikosDataSourceBean,不能再使用其他的连接池替代。xaDataSourceClassName要根据数据库选择相应的类,在数据库对应的驱动包里可以找到。
<bean id="dataSource3" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
<property name="uniqueResourceName" value="key值"/>
<property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource"/>
<property name="xaProperties">
<props>
<prop key="URL">${jdbc.dataSource.url3}</prop>
<prop key="user">${jdbc.dataSource.username3}</prop>
<prop key="password">${jdbc.dataSource.password3}</prop>
</props>
</property>
<property name="minPoolSize" value="${jdbc.dataSource.minimumIdle3}" />
<property name="maxPoolSize" value="${jdbc.dataSource.maximumPoolSize3}" />
<property name="borrowConnectionTimeout" value="${jdbc.dataSource.connectionTimeout3}" />
<property name="testQuery" value="${jdbc.dataSource.connectionTestQuery3}" />
<property name="maintenanceInterval" value="60" />
<property name="maxIdleTime" value="${jdbc.dataSource.idleTimeout3}"></property>
</bean>
然后是JtaTransactionManager事务管理器配置。
JtaTransactionManager有两个重要属性需要配置transactionManager和userTransaction。对应的配置类如下:

注:在jotm中只需配置transactionManager属性
最后是atomikos的配置文件jta.properties。
配置路径:根路径

jta.properties也可命名为transactions.properties,如果不配置也可以启动项目,因为几乎所有配置项都有默认值。
transactions.properties配置

spring多数据源分布式事务的分析与解决方案的更多相关文章
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案
C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...
- Spring Boot2.0之多数据源分布式事务问题
分布式事务解决方案的问题, 分布式事务产生的原因: 多个不同的服务连接不同的数据源 ,做分布式事务的管理. 这种情况是连接两个数据源的情况,然后事务管理器是这样的 只管理了test02的这端业务代码. ...
- spring 多数据源一致性事务方案
spring 多数据源配置 spring 多数据源配置一般有两种方案: 1.在spring项目启动的时候直接配置两个不同的数据源,不同的sessionFactory.在dao 层根据不同业务自行选择使 ...
- SpringBoot 多数据源分布式事务
1.pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- (附源码gitHub下载地址)spring boot -jta-atomikos分布式事务
应用场景:双数据源,就是某些项目会涉及到两个数据源或者两个以上的数据源,这个多数据源的项目一般是数据同步,也就是把数据从另一个系统中,保存到另一个系统,两边的 数据库又不一样,比如一个Mysql.一个 ...
- spring boot:使用分布式事务seata(druid 1.1.23 / seata 1.3.0 / mybatis / spring boot 2.3.2)
一,什么是seata? Seata:Simpe Extensible Autonomous Transcaction Architecture, 是阿里中间件开源的分布式事务解决方案. 前身是阿里的F ...
- Spring Cloud Alibaba分布式事务组件 seata 详解(小白都能看懂)
一,什么是事务(本地事务)? 指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行. 简单的说,事务就是并发控制的单位,是用户定义的一个操作序列. 而一个逻辑工作单元要成 ...
- (WebFlux)003、多数据源R2dbc事务失效分析
一.背景 最近项目持续改造,然后把SpringMVC换成了SpringWebflux,然后把Mybatis换成了R2dbc.中间没有遇到什么问题,一切都那么的美滋滋,直到最近一个新需求的出现,打破了往 ...
- ELK(ElasticSearch, Logstash, Kibana) v5.3.2 分布式日志收集分析最佳解决方案 基于CentOS 7 ( 一 )
[root@localhost temp]# .tar.gz -C /usr/local/ [root@localhost temp]# vim logstatsh_test.conf ======= ...
随机推荐
- python学习笔记(9)函数(一)
定义一个函数 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 (). 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定 ...
- selenium元素定位(一)
Selenium提供了8种定位方式. id name class name tag name link text partial link text xpath css selector 这8种定位方 ...
- spring:事务的5大隔离级别,7大传播行为
一.五大隔离级别 ISOLATION_READ_UNCOMMITTED:读未提交 ISOLATION_READ_COMMITTED:读已提交 ISOLATION_REPEATABLE_READ:可重复 ...
- Mr.Yu
在linux下搭建Git服务器 git服务器环境 服务器 CentOS7 + git(version 1.8.3.1)客户端 Windows10 + git(version 2.16.0.window ...
- FPGA开平方的实现
3种方法: 1.JPL近似的实现方法 `timescale 1ns / 1ps )( clk, syn_rst, dataa, datab, ampout); input clk; :] dataa; ...
- python 3新式类的多继承
因为我用的是python3,所以所用到的类都是新式类,这里我说的都是新式类,python2类的继承复杂一些,主要有新式类和老式类.python3类(新式类)的继承是是广度优先(BFS),实例如下: c ...
- windows下Jmeter压测端口占用问题
https://blog.csdn.net/weixin_43757847/article/details/88188091 1 前情提要人脸识别项目中,云平台新增了人脸识别的校验接口.考虑到存在大量 ...
- c语言函数指针的理解与使用(学习)
1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: 1 2 3 A) char * (*fun1)(char * p1,char * p2); B) char ...
- HDU-3579-Hello Kiki (利用拓展欧几里得求同余方程组)
设 ans 为满足前 n - 1个同余方程的解,lcm是前n - 1个同余方程模的最小公倍数,求前n个同余方程组的解的过程如下: ①设lcm * x + ans为前n个同余方程组的解,lcm * x ...
- 关于(Building tool)的认识以及当下流行的Building tool有哪些?
1.Building tool是什么? (Building tool)构建工具是一种工具,它负责构建流程的所有内容,并自动化与构建项目相关的所有内容.它致力于以下任务: 生成源代码(如果在软件项目中使 ...