码迷,mamicode.com
首页 > 编程语言 > 详细

spring多数据源分布式事务的分析与解决方案

时间:2018-02-22 19:41:26      阅读:500      评论:0      收藏:0      [点我收藏+]

标签:size   一个   通过   turn   string   配置   out   round   nan   

一、概述

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

标签:size   一个   通过   turn   string   配置   out   round   nan   

原文地址:https://www.cnblogs.com/qianjun2017/p/8349829.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!