• 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配置

      

    更多更好的原创https://blog.ccyws.cn
  • 相关阅读:
    人民币大小写转换
    window.parent与window.openner区别
    jquery.honver(),toggle()
    ADO.NET Entity Framework 之“无法加载指定的元数据资源。”
    window.external 的用法(收藏夹功能)
    空链接的技巧
    IIS自动开通组件编程
    在Asp.net中操作IIS的虚拟目录(C#)
    最佳 .NET 网站推荐
    边框 top、clientTop、scrollTop、offsetTop
  • 原文地址:https://www.cnblogs.com/qianjun2017/p/8349829.html
Copyright © 2020-2023  润新知