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

使用dynamic-datasource-spring-boot-starter做多数据源及源码分析 多数据源系列 1、spring boot2.0 +Mybatis + druid搭建一个最简单的多数据源 2、利用Spring的AbstractRoutingDataSource做多数据源动态切换 3、使用dynamic-datasource-spring-boot-starter做多数据源及源码分析 文章目录多数据源系列简介实操基本使用集成druid连接池源码分析整体结构总结 简介 前两篇博客介绍了用基本的方式做多数据源,可以应对一般的情况,但是遇到一些复杂的情况,比如:动态增减数据源、数据源分组,纯粹多 阅读详情

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

分布式事务解决方案的问题,

分布式事务产生的原因:

  多个不同的服务连接不同的数据源 ,做分布式事务的管理。

 

这种情况是连接两个数据源的情况,然后事务管理器是这样的 只管理了test02的这端业务代码。所以test02的这个会回滚!

但是test01会入库哦

这属于传统的分布式事务解决方案

   使用springboot+jta+atomikos 分布式事物管理 (不适合微服务,需要拿到数据源然后注册到同一个全局事务里面去)

好了废话不多说,动手撸代码!

引入的jar:

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

配置文件也要修改:

application.properties:

# Mysql 1
mysql.datasource.test1.url = jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8
mysql.datasource.test1.username = root
mysql.datasource.test1.password = root

mysql.datasource.test1.minPoolSize = 3
mysql.datasource.test1.maxPoolSize = 25
mysql.datasource.test1.maxLifetime = 20000
mysql.datasource.test1.borrowConnectionTimeout = 30
mysql.datasource.test1.loginTimeout = 30
mysql.datasource.test1.maintenanceInterval = 60
mysql.datasource.test1.maxIdleTime = 60



# Mysql 2
mysql.datasource.test2.url =jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8
mysql.datasource.test2.username =root
mysql.datasource.test2.password =root

mysql.datasource.test2.minPoolSize = 3
mysql.datasource.test2.maxPoolSize = 25
mysql.datasource.test2.maxLifetime = 20000
mysql.datasource.test2.borrowConnectionTimeout = 30
mysql.datasource.test2.loginTimeout = 30
mysql.datasource.test2.maintenanceInterval = 60
mysql.datasource.test2.maxIdleTime = 60

 然后创建包:com.toov5.configure

 

 

 

 

 底层原理是使用的2PC

 

package com.toov5.configure;

import org.springframework.boot.context.properties.ConfigurationProperties;

import lombok.Data;

@Data
@ConfigurationProperties(prefix = "mysql.datasource.test1")
public class DBConfig1 {

    private String url;
    private String username;
    private String password;
    private int minPoolSize;
    private int maxPoolSize;
    private int maxLifetime;
    private int borrowConnectionTimeout;
    private int loginTimeout;
    private int maintenanceInterval;
    private int maxIdleTime;
    private String testQuery;
}
package com.toov5.configure;

import org.springframework.boot.context.properties.ConfigurationProperties;

import lombok.Data;
//读取解析配置文件,获取值
@Data
@ConfigurationProperties(prefix = "mysql.datasource.test2")
public class DBConfig2 {

    private String url;
    private String username;
    private String password;
    private int minPoolSize;
    private int maxPoolSize;
    private int maxLifetime;
    private int borrowConnectionTimeout;
    private int loginTimeout;
    private int maintenanceInterval;
    private int maxIdleTime;
    private String testQuery;
}

datasource包下面:

package com.toov5.datasource;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import com.toov5.configure.DBConfig1;

@Configuration
// basePackages 最好分开配置 如果放在同一个文件夹可能会报错
//跟之前都一样。扫包然后指定工厂
//没有配置事务管理器,相当于将本地事务注册到Atomikos全局事务
@MapperScan(basePackages = "com.toov5.test01", sqlSessionTemplateRef = "testSqlSessionTemplate")
public class MyBatisConfig1 {

    // 配置数据源
    
    @Bean(name = "testDataSource")
    public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
        MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
        mysqlXaDataSource.setUrl(testConfig.getUrl());
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXaDataSource.setPassword(testConfig.getPassword());
        mysqlXaDataSource.setUser(testConfig.getUsername());
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
 
        
        //创建Atomikos全局事务,所有的事务注册进来
        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXaDataSource);
        xaDataSource.setUniqueResourceName("testDataSource"); //testDataSource这个数据源的注册

        xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
        xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
        xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
        xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
        xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
        xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
        xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
        xaDataSource.setTestQuery(testConfig.getTestQuery());
        return xaDataSource;
    }

    
    @Bean(name = "testSqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    
    @Bean(name = "testSqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
package com.toov5.datasource;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import com.toov5.configure.DBConfig2;

@Configuration
@MapperScan(basePackages = "com.toov5.test02", sqlSessionTemplateRef = "test2SqlSessionTemplate")
public class MyBatisConfig2 {

    // 配置数据源
    @Bean(name = "test2DataSource")
    public DataSource testDataSource(DBConfig2 testConfig) throws SQLException {
        MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
        mysqlXaDataSource.setUrl(testConfig.getUrl());
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXaDataSource.setPassword(testConfig.getPassword());
        mysqlXaDataSource.setUser(testConfig.getUsername());
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXaDataSource);
        xaDataSource.setUniqueResourceName("test2DataSource");

        xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
        xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
        xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
        xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
        xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
        xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
        xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
        xaDataSource.setTestQuery(testConfig.getTestQuery());
        return xaDataSource;
    }

    @Bean(name = "test2SqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    @Bean(name = "test2SqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

 

 

 service中的事务管理不需要去写了!

package com.toov5.test02.service02;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.toov5.test01.mappertest01.UserMapperTest01;
import com.toov5.test02.mappertest02.UserMapperTest02;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class UserService02 {
  @Autowired
  private UserMapperTest01 userMapperTest01;
  @Autowired
  private UserMapperTest02 userMapperTest02;
 
  
  @Transactionalpublic int test01Andtest02(String name, Integer age){
        //连接两个数据源
          int result1 = userMapperTest01.insert(name, age);
          int result2 = userMapperTest02.insert(name, age);
          int i = 1/0;
          int result = result1+result2;
          return result;
      }
  
}

 

目录结构:

项目启动类

package com.toov5.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import com.toov5.configure.DBConfig1;
import com.toov5.configure.DBConfig2; @SpringBootApplication(scanBasePackages={"com.toov5.*"}) @EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class }) //开启读取配置文件,启动时候去读取配置文件 public class app { public static void main(String[] args) { SpringApplication.run(app.class, args); } }

 

 ok,到此为止。是不是很简单呀~

 

posted @ 2018-10-20 02:55 toov5 阅读( ...) 评论( ...) 编辑 收藏
Spring Boot Druid 多数据源 Atomikos 分布式事务 1、前言由于最近需要做一个接口平台,用到了两个数据库(业务库和系统库分离),需要考虑同时操作两个数据库的数据时事务的管理,这时搜索了下资料,发现使用分布式事务可满足现状需求。之前也没接触过分布式事务,在baidu、google了一遍之后,根据相关的示例也未成功搭建。在一番折腾之后,终于搭建成功, 现将其记录下来,也为将来有此需求的朋友提供一点帮助。2、名词解释1、Spring Boot:Spring 阅读详情

相关推荐

Spring Boot:mybatis-plus + atomikos + druid 实现不同实例数据库的多数据源配置和分布式事务管理

想到工作上可能会用到多数据源,但是自己在这方面并不是很熟悉,于是在网上查阅了很多文章,结果发现,网上的文章要么版本太老有些过时,要么用的不是mybatis-plus而是mybaits,要么步骤繁琐、需要自己手动编写aop切面代码,要么在同一service层方法中只能使用@Transactional实现单个数据源的事务管理控制,总是觉得有点不太完美,所以综合了以上文章的不足之处和可以借鉴之处,在这里总结出了一个万能的、可以适应多方面需求的多数据源配置方法,以满足相对完整的、代码简练的分布式事务控制需求。 一.

朗朗繁星的博客 1543

“分布式事务”的理解(适用于访问多个数据库之间)

原文地址:http://blog.163.com/soli1988_blog/blog/static/176895272201212812416747/ 总体来看,如果所有数据的修改仅依靠单个数据源就能完成,则这个事务就相当简单了。然而,随着商业需求的日益增加,应用程序变得越来越复杂,经常需要访问多个数据库,这些数据库通常分布在不同的地方,这就是分布式事务。分布式事务修改的数据存...

数据库 609

springboot2.6+Mybatis注解多数据源使用dynamic-datasource-spring-boot-starter为依赖

多数据源系列 1、springboot2.6+Mybatis静态多数据源(集成JTA(Atomikos案例)实现分布式事务控制) 2、springboot2.6+Mybatis动态多数据源AOP切换(AbstractRoutingDataSource) 3、springboot2.6+Mybatis注解多数据源使用dynamic-datasource-spring-boot-starter为依赖 说明 前两篇博客介绍了用基本的方式做多数据源,可以应对一般的情况,但是遇到一些复杂的情况就需要扩展下功能了,比如

qq_34246965的博客 4045

SpringBoot2实现多数据源及分布式事务

SpringBoot2实现多数据源及分布式事务SpringBoot2实现多数据源及分布式事务多数据源简介分布式事务简介环境简介代码片段Maven依赖:pom.xml配置文件:application.properties数据源1配置读取类:FirstDBConfig.java数据源2配置读取类:SecondDBConfig.java配置数据源1:FirstDataSourceConfig.java配...

z_junyu的博客 3336

Spring Boot入门(20):使用Mybatis-plus实现Spring Boot多数据源配置,轻松实现数据库读写分离!

如何实现多数据源的配置及项目使用,此文教会你,超级简单,开箱即用。

**My Coding Family** 2万+

springboot多数据源即分布式事务解决方案

实现系统对多数据源的操作。 实现系统对多数据源的分布式事务管理,包括事务的提交和回滚。

【SpringBoot2.0】基于Atomikos的多数据源分布式事务(XA)解决方案

最近工作中在同一项目中用到了多数据源,虽然项目本身对多数据源的事务没有要求,甚至可以不使用事务。但是本着精益求精的原则,加上各种资料的查阅,终于实现了多数据源的XA(分布式事务) 项目框架 springboot2.0.x springmvc mybatis 对多数据源的mapper的处理 针对多个数据源,mapper通常有两种处理方式:一种是将各个数据源对应的mapper放置在...

Simon's Dream 7230

SpringBoot整合多数据源,并实现本地分布式事务

SpringBoot整合多数据源,并实现本地分布式事务。实现读写分离。

spring boot多数据源 分布式事务管理

https://www.cnblogs.com/xiaofengfeng/p/9049363.html

cpzhanghao的博客 3181

Miniconda入门:在CentOS上的安装、基本操作、目录结构、卸载

Miniconda是一个 免费的 轻量级的 conda安装程序 它只包含conda、Python、pip、zlib等基础的文件和依赖包 使用conda install命令可从Anaconda存储库中安装额外的conda包 简介 下载 安装 基本操作 虚拟环境的操作 包的操作 目录结构 卸载

ArYe 1万+

滚动轴承振动信号特征解析与故障诊断模型构建

本文深入解析了滚动轴承振动信号的三大来源与特征,并详细阐述了从时域、频域到时频域的特征提取方法。通过构建基于机器学习(如随机森林、SVM)或深度学习的故障诊断模型,结合实战代码示例,为设备维护工程师提供了一套从信号分析到智能诊断的完整解决方案,旨在实现精准的故障识别与预测性维护。

qsc901234567的博客 368

spring boot + druid + mybatis + atomikos 多数据源配置 并支持分布式事务

文章目录一、综述1.1 项目说明1.2 项目结构二、配置多数据源并支持分布式事务2.1 导入基本依赖2.2 在yml中配置多数据源信息2.3 进行多数据源的配置1. 在启动类关闭springboot对数据源的自动化配置,由我们手动进行多数据源的配置2. 创建多数据源配置类`DataSourceFactory.java`, 手动配置多数据源3. 自定义sqlSessionTemplate的...

黑白影的博客 9018

POWER SI仿真流程

一、打开软件Power SI二、加载PCB,可以直接使用brd文件,不用再进行格式转换三、check Stackup,与原来的PCB叠层对照一遍,检查数据加载后有没有出错。四、select Nets,加载brd文件后,可能所有的网络都处于使用状态,先在右侧net manager下面右键disable all nets,再使能需要仿真的电源网络(如果要仿真的网络没有归属到电源网络,在其上右键,选classfy as power \ground nets)

lx5213的博客 1321

基于spring boot项目的多数据源配置与分布式事务处理总结

多数据源配置 项目存在10个数据源,如下 core_biz 业务逻辑 数据库core_sys 系统设置 数据库fund_pool 资金池 数据库 分用户拆分了8个库 针对这10个数据源,分别进行创建 首先为业务逻辑数据库创建数据源,定义为Java Bean @Configuration及@Bean注解的使用不做赘述 @Configuration public c

逍遥飞鹤的专栏 1万+

Rockit VDEC解码实战:从零构建高效视频处理流水线

本文详细介绍了Rockit VDEC硬件解码模块在RK3568/RK3588平台的应用实践,涵盖开发环境配置、MPI接口使用、码流发送模式选择、内存管理优化及多路解码系统构建。通过实战案例展示如何利用VDEC实现高效视频处理流水线,显著降低CPU占用率,提升嵌入式多媒体开发效率。

ol789012的博客 305

超详细!思岚S2激光雷达hector_mapping建图

使用思岚S2激光雷达,在ros平台上利用hector_mapping功能包实现建图功能

m0_50965539的博客 5591

spring yml 配置事务_Spring Boot解决多数据源分布式事务的问题

Spring Boot解决多数据源分布式事务的问题一、问题产生背景 Spring Boot处理多数据源可以采用MyBatis-Plus解决方案,多数据源处理数据时引发分布式事务的问题,本文讲解如何处理多数据源分布式事务。二、构建多数据源步骤一、构建Spring Boot工程 org.springframework.boot spring-boot-starter-parent 2.1.6.RELE...

weixin_42301367的博客 452

ARM CoreSight架构

CoreSight架构是现代复杂SoC的“飞行数据记录仪”(黑匣子)和“精密诊断仪”的结合体。它彻底改变了嵌入式系统的调试方式,从传统的“盲人摸象”变成了拥有“上帝视角”,是ARM生态系统能够支撑起从微控制器到高性能服务器芯片如此广泛产品线的重要基石技术之一。

guigenyi的专栏 1422

spring boot + mybatis plus + 多数据源 + 分布式事务

本文介绍一种使用spring boot + mybatis plus + 多数据源 + 分布式事务 的实现方式。 由于涉及多个数据库,自然就涉及到分布式事务。先了解几个概念: 1、XA是什么? XA是由X/Open组织提出的分布式事务的规范。XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口。 ...

CodingSoldier的博客 6396

Java 网络编程(超级详细)

1. 网络编程 1.1 网络编程概述 计算机网络 是指将地理位置相同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及通信协议的管理和协调下,实现资源共享和信息传递的计算机系统 1.2 网络编程三要素 1、IP地址 要想让网络中的计算机能够互相通信,必须为计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,而IP地址就是这个标识号,也就是设备的标识。 2、端口 网络的通信,本质上是两个应用程序的通信。每台计算机都有很多的应用程

imByte的博客 3万+

【数据同化第二期】数据同化中三大理论基础之一(最小方差估计)

【数据同化第二期】深入理解数据同化及经典案例(最小方差估计)

WW、forever的博客 1597

动态多数据源使用seata实现分布式事务

一、背景 目前公司很多应用因为历史原因,一个应用访问多个数据库进行插入和更新操作,这就可能产生数据一致性问题,同时应用如果跨服务的调用也可能会产生事务问题。 目前应用是采用dynamic-datasource-spring-boot-starter做多数据源控制的。而seata是一款开源的分布式事务框架。我们了解到dynamic-datasource-spring-boot-starter的新版本已经支持基于seata的分布式事务了,而官网的例子基本都是标准的单数据源的整合,下面我们分别对dynam..

IT巅峰技术专栏 4745

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Spring Boot mybatis-plus 多数据源配置

创建一个注解,用于在需要切换数据源的方法上进行标识。

专注于技术分享 1460

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Dynamic-Datasource多模块依赖管理:Spring Boot多数据源终极配置指南

在Spring Boot项目中实现多数据源配置,Dynamic-Datasource提供了完整的解决方案。这个强大的开源项目支持动态数据源切换、主从分离、读写分离和分布式事务管理,让复杂的数据库架构变得简单可控。本文将为您详细解析如何正确配置和管理Dynamic-Datasource的多模块依赖关系。 ## 🎯 项目架构概览 Dynamic-Datasource采用多模块设计,每个模块都有明

gitblog_00769的博客 862

Spring Boot 多数据源事务管理

场景推荐方案说明单数据源事务默认配置,性能高多数据源事务(强一致性)(XA)支持 ACID,性能较低多数据源事务(高并发)支持最终一致性,性能高微服务架构Seata、Saga 模式适合分布式系统,解耦服务间事务。

红血哥 1069
上一篇: Spring Boot2.0之多数据源事务管理
下一篇: windows下的git使用指令
Art&Code
博客等级 码龄7年 77粉丝 554原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值