一、概述

  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多数据源分布式事务的分析与解决方案的更多相关文章

  1. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案

    C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...

  2. Spring Boot2.0之多数据源分布式事务问题

    分布式事务解决方案的问题, 分布式事务产生的原因: 多个不同的服务连接不同的数据源 ,做分布式事务的管理. 这种情况是连接两个数据源的情况,然后事务管理器是这样的 只管理了test02的这端业务代码. ...

  3. spring 多数据源一致性事务方案

    spring 多数据源配置 spring 多数据源配置一般有两种方案: 1.在spring项目启动的时候直接配置两个不同的数据源,不同的sessionFactory.在dao 层根据不同业务自行选择使 ...

  4. SpringBoot 多数据源分布式事务

    1.pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  5. (附源码gitHub下载地址)spring boot -jta-atomikos分布式事务

    应用场景:双数据源,就是某些项目会涉及到两个数据源或者两个以上的数据源,这个多数据源的项目一般是数据同步,也就是把数据从另一个系统中,保存到另一个系统,两边的 数据库又不一样,比如一个Mysql.一个 ...

  6. 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 ...

  7. Spring Cloud Alibaba分布式事务组件 seata 详解(小白都能看懂)

    一,什么是事务(本地事务)? 指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行. 简单的说,事务就是并发控制的单位,是用户定义的一个操作序列.      而一个逻辑工作单元要成 ...

  8. (WebFlux)003、多数据源R2dbc事务失效分析

    一.背景 最近项目持续改造,然后把SpringMVC换成了SpringWebflux,然后把Mybatis换成了R2dbc.中间没有遇到什么问题,一切都那么的美滋滋,直到最近一个新需求的出现,打破了往 ...

  9. ELK(ElasticSearch, Logstash, Kibana) v5.3.2 分布式日志收集分析最佳解决方案 基于CentOS 7 ( 一 )

    [root@localhost temp]# .tar.gz -C /usr/local/ [root@localhost temp]# vim logstatsh_test.conf ======= ...

随机推荐

  1. async包 ES6 async/await的区别

    最基本的async 包 ApCollection.find({}).toArray(function (err, aps) { var num = 0; async.whilst( function ...

  2. 对H5新增多线程的理解与简单使用

    由于JavaScript的特性决定了JavaScript语言是一种单线程语言,但是有时候我们需要使用多线程比如进行大量的计算时.H5为此新增了多线程的方法. 在这里我是用JavaScript来实现著名 ...

  3. 使用Connector / Python连接MySQL/查询数据

    使用Connector / Python连接MySQL connect()构造函数创建到MySQL服务器的连接并返回一个 MySQLConnection对象 在python中有以下几种方法可以连接到M ...

  4. shell清除文件内容脚本

    先来代码: [root@localhost Qingchu]# cat Qingchu.sh #!/bin/bash #描述: #作者:孤舟点点 #版本:1.0 #创建时间:-- :: PATH=/b ...

  5. Matplotlib绘图库入门(七):高效使用

    原文地址: !()[http://www.bugingcode.com/blog/Matplotlib_7_Effectively_Using.html] 这是一篇关于如何高效的使用Matplotli ...

  6. XML的四种解析器(dom_sax_jdom_dom4j)原理及性能比较[收藏]

    1)DOM(JAXP Crimson解析器)    DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定 ...

  7. myeclipse安装插件svn的步骤

    下载插件地址:http://subclipse.tigris.org/ 方法一:本地安装 1.打开HELP->MyEclipse Configuration或者myeclipse->MyE ...

  8. Proto3:编码

    本文介绍protocol buffer消息二进制传输格式.在应用程序中使用protocol buffer时,你并不需要了解这些,但它对你了解protocol buffer格式如何影响你的编码消息的大小 ...

  9. 【转】PHP中被忽略的性能优化利器:生成器.md

      PHP  如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明 ...

  10. 添砖加瓦:Linux /proc目录简介

    Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构.改变内核设置的机制.proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它以文件系统的方式为访问系 ...