Spring中使用atomikos+druid实现经典分布式事务

spring-boot入门(七)atomikos+druid+多数据源下的分布式事务配置 spring-boot入门(七)atomikos+druid+多数据源下的分布式事务配置 本章内容是基于spring-boot入门(六)多数据源的基础之上进行的,如果还不了解多数据源怎么配置,请参考上一章节的内容。在上一章节的末尾我们遗留了一个问题:多数据源下的分布式事务问题。在分布式事务下我们需要使用JTA(Java Transaction API)事务来处理事务,保证事务的强一致性,即要成功... 阅读详情

经典分布式事务,是相对互联网中的柔性分布式事务而言,其特性为ACID原则,包括原子性(Atomictiy)、一致性(Consistency)、隔离性(Isolation)、持久性(Durabilit):

  • 原子性:事务是一个包含一系列操作的原子操作。事务的原子性确保这些操作全部完成或者全部失败。
  • 一致性:一旦事务的所有操作结束,事务就被提交。然后你的数据和资源将处于遵循业务规则的一直状态。
  • 隔离性:因为同时在相同数据集上可能有许多事务处理,每个事务应该与其他事务隔离,避免数据破坏。
  • 持久性:一旦事务完成,他的结果应该能够承受任何系统错误(想象一下在事务提交过程中机器的电源被切断的情况)。通常,事务的结果被写入持续性存储。

XA是啥?
XA是由X/Open组织提出的分布式事务的架构(或者叫协议)。XA架构主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口。XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁。也就是说,在基于XA的一个事务中,我们可以针对多个资源进行事务管理,例如一个系统访问多个数据库,或即访问数据库、又访问像消息中间件这样的资源。这样我们就能够实现在多个数据库和消息中间件直接实现全部提交、或全部取消的事务。XA规范不是java的规范,而是一种通用的规范,
目前各种数据库、以及很多消息中间件都支持XA规范。
JTA是满足XA规范的、用于Java开发的规范。所以,当我们说,使用JTA实现分布式事务的时候,其实就是说,使用JTA规范,实现系统内多个数据库、消息中间件等资源的事务。

JTA(Java Transaction API),是J2EE的编程接口规范,它是XA协议的JAVA实现。它主要定义了:

  • 一个事务管理器的接口javax.transaction.TransactionManager,定义了有关事务的开始、提交、撤回等>操作。
  • 一个满足XA规范的资源定义接口javax.transaction.xa.XAResource,一种资源如果要支持JTA事务,就需要让它的资源实现该XAResource接口,并实现该接口定义的两阶段提交相关的接口。如果我们有一个应用,它使用JTA接口实现事务,应用在运行的时候,就需要一个实现JTA的容器,一般情况下,这是一个J2EE容器,像JBoss,Websphere等应用服务器。但是,也有一些独立的框架实现了JTA,例如Atomikos, bitronix都提供了jar包方式的JTA实现框架。这样我们就能够在Tomcat或者Jetty之类的服务器上运行使用JTA实现事务的应用系统。在上面的本地事务和外部事务的区别中说到,JTA事务是外部事务,可以用来实现对多个资源的事务性。它正是通过每个资源实现的XAResource来进行两阶段提交的控制。感兴趣的同学可以看看这个接口的方法,除了commit, rollback等方法以外,还有end(), forget(), isSameRM(), prepare()等等。光从这些接口就能够想象JTA在实现两阶段事务的复杂性。

本篇以Spring MVC+Maven+Atomikos+Druid+MyBatis演示分布式事务的实现。

Mave 的pom.xml

<properties>
	<jdk.version>1.8</jdk.version>
	<!-- 注mysql的版本和druid的版本一定要搭配,否则会有问题,目前这两个版本是搭配好的 -->
	<mysql.version>8.0.11</mysql.version>
	<druid.version>1.1.17</druid.version>
	<spring.version>5.1.8.RELEASE</spring.version>
	<cglib.version>3.2.12</cglib.version>
	<atomikos.version>5.0.0</atomikos.version>
	<aspectjweaver.version>1.9.4</aspectjweaver.version>
	<aspectjrt.version>1.5.4</aspectjrt.version>
	<jta.version>1.1</jta.version>
	<mybatise.version>3.2.0</mybatise.version>
	<mybatis.spring>1.2.0</mybatis.spring>
	<log4j.version>1.2.17</log4j.version>
	<junit.version>4.12</junit.version>
	<cglib.version>3.2.4</cglib.version>
</properties>
<dependencies>
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>${mybatise.version}</version>
	</dependency>
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis-spring</artifactId>
		<version>${mybatis.spring}</version>
	</dependency>
	<dependency>
		<groupId>com.atomikos</groupId>
		<artifactId>atomikos-util</artifactId>
		<version>${atomikos.version}</version>
	</dependency>
	<dependency>
		<groupId>com.atomikos</groupId>
		<artifactId>transactions</artifactId>
		<version>${atomikos.version}</version>
	</dependency>
	<dependency>
		<groupId>com.atomikos</groupId>
		<artifactId>transactions-jta</artifactId>
		<version>${atomikos.version}</version>
	</dependency>
	<dependency>
		<groupId>com.atomikos</groupId>
		<artifactId>transactions-jdbc</artifactId>
		<version>${atomikos.version}</version>
	</dependency>
	<dependency>
		<groupId>com.atomikos</groupId>
		<artifactId>transactions-api</artifactId>
		<version>${atomikos.version}</version>
	</dependency>
	<dependency>
		<groupId>javax.transaction</groupId>
		<artifactId>jta</artifactId>
		<version>${jta.version}</version>
	</dependency>
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib-nodep</artifactId>
		<version>${cglib.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-beans</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-orm</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context-support</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<!-- Spring Aop依赖jar -->
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>${aspectjweaver.version}</version>
	</dependency>

	<dependency>
		<groupId>aspectj</groupId>
		<artifactId>aspectjrt</artifactId>
		<version>${aspectjrt.version}</version>
	</dependency>
	<!-- CGLIB -->
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>${cglib.version}</version>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>${mysql.version}</version>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>${druid.version}</version>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>${junit.version}</version>
		<scopte>test</scope>
	</dependency>
</dependencies>

spring-application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
     <!-- 1. 数据源配置 -->
    <context:property-placeholder location="classpath*:*.properties" file-encoding="utf8" />
	<bean id="utf8" class="java.lang.String">
		<constructor-arg value="utf-8"></constructor-arg>
	</bean>
    <!-- 开启异步任务(同时开启定时器注解扫描) -->
    <task:annotation-driven />
    <!-- 使用@AspectJ风格的切面声明 -->
    <!-- <aop:aspectj-autoproxy/> -->
    <!-- 使用Annotation自动注册Bean -->
    <!-- 在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解 -->
    <context:component-scan base-package="net.xiake6"><!-- base-package 如果多个,用“,”分隔 --> 
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>  
    <!-- 引入Mybatis配置 -->
    <!-- <import resource="spring-mybatis-atomikos-druid.xml"/> -->
    <import resource="spring-mybatis-atomikos-druid.xml"/>
</beans>

spring-mybatis-atomikos-druid.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/jee 
    http://www.springframework.org/schema/jee/spring-jee-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"
    default-lazy-init="true">   

	<context:annotation-config />
	<!-- 使用Druid使为XA数据源 -->
    <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true">
        <property name="xaDataSourceClassName" value="com.alibaba.druid.pool.xa.DruidXADataSource"/>
        <property name="xaProperties">
            <props>
            	<prop key="driverClassName">${jdbc.driverClassName}</prop>
            	<!-- 配置初始化大小、最小、最大 -->
				<prop key="initialSize">10</prop>
				<prop key="minIdle">3</prop>
				<prop key="maxActive">100</prop>
				<!-- 配置获取连接等待超时的时间 -->
				<prop key="maxWait">60000</prop>
				<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
				<prop key="timeBetweenEvictionRunsMillis">60000</prop>
				<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
				<prop key="minEvictableIdleTimeMillis">300000</prop>
				<prop key="validationQuery">SELECT 'x'</prop>
				<prop key="testWhileIdle">true</prop>
				<prop key="testOnBorrow">false</prop>
				<prop key="testOnReturn">false</prop>
				<!-- 配置监控统计拦截的filters -->
				<prop key="filters">stat</prop>
            </props>
        </property>
    </bean>
    <!-- 配置数据源一 -->
    <bean id="dataSourceOne" parent="abstractXADataSource">
        <property name="uniqueResourceName">
            <value>dataSourceOne</value>
        </property>
        <property name="xaProperties">
            <props>
                <prop key="url">${jdbc.url}</prop>
                <prop key="username">${jdbc.username}</prop>
                <prop key="password">${jdbc.password}</prop>
            </props>
        </property>
    </bean>
    <!--配置数据源二-->
    <bean id="dataSourceTwo" parent="abstractXADataSource">
        <property name="uniqueResourceName">
            <value>dataSourceTwo</value>
        </property>
        <property name="xaProperties">
            <props>
                <prop key="url">${jdbc.two.url}</prop>
                <prop key="username">${jdbc.two.username}</prop>
                <prop key="password">${jdbc.two.password}</prop>
            </props>
        </property>
    </bean>
    
    <!--mybatis的相关配置-->
    <bean id="sqlSessionFactoryOne" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSourceOne"/>
        <property name="mapperLocations" value="classpath*:mapping/ds1/*.xml"/>
    </bean>
    
    <bean id="sqlSessionFactoryTwo" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSourceTwo"/>
        <property name="mapperLocations" value="classpath*:mapping/ds2/*.xml"/>
    </bean>
    
    <!--配置mybatis映射文件自动扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="net.xiake6.dao.ds1"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryOne"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="net.xiake6.dao.ds2"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryTwo"/>
    </bean>

    <!--配置分布式事务-->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
        <property name="forceShutdown" value="false"/>
    </bean>
    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
        <property name="transactionTimeout" value="3000"/>
    </bean>
    <!--JTA事务管理器-->
    <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <ref bean="atomikosTransactionManager"/>
        </property>
        <property name="userTransaction">
            <ref bean="atomikosUserTransaction"/>
        </property>
        <property name="allowCustomIsolationLevels" value="true"/>
    </bean>
   
    
    <aop:config proxy-target-class="true">  
        <aop:advisor pointcut="execution(* *net.xiake6.service..*(..))" advice-ref="txAdvice" />  
    </aop:config>  
    <tx:advice id="txAdvice" transaction-manager="jtaTransactionManager">  
        <tx:attributes>  
            <tx:method name="insert*"  propagation="REQUIRED" read-only="false" rollback-for="*Exception"/>
            <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="*Exception" />  
            <tx:method name="save*"  propagation="REQUIRED"  read-only="false" rollback-for="*Exception" />    
            <tx:method name="delete*"  propagation="REQUIRED"  read-only="false" rollback-for="*Exception" />  
            <tx:method name="del*"  propagation="REQUIRED"  read-only="false" rollback-for="*Exception" />  
            <tx:method name="update*"  propagation="REQUIRED"  read-only="false" rollback-for="*Exception" />
            <tx:method name="select*"  propagation="REQUIRED"  read-only="true" />
            <tx:method name="query"  propagation="REQUIRED"  read-only="true" />
        </tx:attributes>  
    </tx:advice>
    
    <!-- 配置事务管理 -->
    <tx:annotation-driven transaction-manager="jtaTransactionManager" />
</beans>

jdbc.properties

#mysql 6.*以上
jdbc.driverClassName = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&pinGlobalTxToPhysicalConnection=true&useSSL=false
jdbc.username =root
jdbc.password =root

jdbc.two.url = jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&pinGlobalTxToPhysicalConnection=true&useSSL=false
jdbc.two.username =root
jdbc.two.password =root

jta.properties

com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.console_file_name=tm.release.out
com.atomikos.icatch.log_base_name=tm.releaselog
com.atomikos.icatch.tm_unique_name=com.atomikos.spring.jdbc.tm.release
com.atomikos.icatch.console_log_level=INFO

TestInsert.java

@ContextConfiguration(value = {"classpath:spring-application-context.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class TestInsert {
	private Logger logger = LoggerFactory.getLogger(TestInsert.class);
	@Autowired
	private BatchInsertService batchInsertService;

	@Test
	public void insert(){
		
		long startTime = System.currentTimeMillis();
		User user = new User();
		user.setName("User_"+(int)(Math.random()*100));
		user.setAge((int)(Math.random()*100));
		
		CustInfo info = new CustInfo();
		info.setPhone("123456789"+(int)(Math.random()*100));
		batchInsertService.insert(user,info);
		
		long endTime = System.currentTimeMillis();
		logger.info("共耗时:{}毫秒",endTime -startTime);
	}
}

BatchInsertService.java

@Service
public class BatchInsertService {
	private Logger logger = LoggerFactory.getLogger(BatchInsertService.class);
	@Autowired
	private UserService userService;
	@Autowired
	private CustInfoService custInfoService;
	@Transactional(rollbackFor= {Exception.class,RuntimeException.class})
	public void insert(User user,CustInfo custInfo) {
		int insertUser =  userService.insert(user);
		logger.info("insertUser={}",insertUser);
		int insertCustInfo = custInfoService.insert(custInfo);
		logger.info("insertCustInfo={}",insertCustInfo);
	}
}

UserService.java

@Service
public class UserService {
	@Autowired
	private UserMapper userMapper;
	
	public int insert(User record) {
		int result = userMapper.insert(record);
		return result;
	}
	
}

CustInfoService.java

@Service
public class CustInfoService {
	@Autowired
	private CustInfoMapper custInfoMapper;

	public int insert(CustInfo record) {
		int result = custInfoMapper.insert(record);
		long now = System.currentTimeMillis();
		// 模拟一个异常
		if (now % 2 == 0) {
			throw new RuntimeException("CustInfoMapper throws test insert exception");
		}
		return result;
	}
}

Mapper和Bean等就不列出来了,完成的示例工程在github:https://github.com/fenglibin/DruidWithAtomikos

解决处理因atomikos整合druid出现的com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet的bug 解决处理因atomikos整合druid出现的com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 70,103,716 milliseconds ago. The last packet sent successfully to the server was 70,103,716 milliseconds ago. 阅读详情

相关推荐

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

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

朗朗繁星的博客 1543

Springboot多数据源集成druid+atomikos,出现CommunicationsException错误:The client was disconnected by the server

Springboot集成多数据源事物就使用了atomikos框架,然后在线上发现报CommunicationsException异常的错误,因为晚上没有人使用,所以我猜是因为长时间没有连数据库导致的。

wien717651800的博客 1915

Spring Boot Druid 多数据源 Atomikos 分布式事务

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

追逐梦想的专栏 3万+

atomikos数据源连接超时和耗尽问题

问题描述 项目里之前用的是原生druid数据源,没有任何问题。 后来使用了AtomikosDataSourceBean,其中用的DruidXADataSource数据源,java配置如下 @Bean(name = "bdpDatasource") public DataSource bdpDatasource() { DruidXADataSource druidXADataSource = new DruidXADataSource(); druidXADataS

cyh的博客 4793

Spring Boot Druid 多数据源 Atomikos 分布式事务缺陷

多数据源动态加载事务控制 源码下载地址:https://github.com/qingqiangqiang/dynamic_datasource.git 根据spring boot官方文档描述,如果spring boot检测到了jta环境,会自动进行配置,故此处不需要进行事务配置 官方地址:http://docs.spring.io/spring-boot/docs/current/re...

莫然的博客 3597

Atomikos分布式事务中切换数据源

分布式XA事务管理,多数据源动态切换, atomikos

ErixHao的专栏 7030

druid分布式mysql_Spring中使用atomikos+druid实现经典分布式事务的方法

经典分布式事务,是相对互联网中的柔性分布式事务而言,其特性为ACID原则,包括原子性(Atomictiy)、一致性(Consistency)、隔离性(Isolation)、持久性(Durabilit):原子性:事务是一个包含一系列操作的原子操作。事务的原子性确保这些操作全部完成或者全部失败。一致性:一旦事务的所有操作结束,事务就被提交。然后你的数据和资源将处于遵循业务规则的一直状态。隔离性:因为同...

weixin_39877166的博客 276

Spring整合Atomikos与Druid实现分布式事务完整Demo

Spring通过高度抽象的事务管理接口,将事务管理的实现与具体的数据访问技术解耦,使得开发者可以在不同事务管理策略之间灵活切换。其核心抽象包括和三个关键接口。是Spring提供的抽象类,用于实现动态数据源切换。Atomikos 是一个开源的 JTA(Java Transaction API)事务管理器,专为分布式系统设计。它实现了 XA 协议,支持跨多个资源(如数据库、消息队列)的事务一致性。

weixin_29903713的博客 795

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

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

黑白影的博客 9018

Spring Boot与Druid, Mybatis和Atomikos的多数据源分布式事务配置教程

Spring Boot自推出以来,迅速成为Java开发者实现快速应用开发的首选框架。它的核心特性包括自动配置、内嵌服务器和无需配置的“约定优于配置”的理念,极大简化了项目搭建和维护的复杂性。通过约定好的默认设置,开发者可以迅速开始编写业务代码,而不需要进行繁琐的配置。自动配置机制是Spring Boot的灵魂,其灵感来源于“约定优于配置”的设计原则。Spring Boot自动配置了大量常用的库,例如内嵌的Tomcat、Jetty或Undertow Web服务器以及Spring MVC。

weixin_42594419的博客 1299

Spring、Druid与AtomikosDataSource实现高效多数据源与分布式事务管理

在分布式系统中,跨多个服务或数据库操作的事务称为分布式事务。确保这些事务能够在不同节点间保持一致性是分布式系统设计的关键挑战之一。事务一致性问题通常涉及CAP定理,该定理表明在分布式计算系统中,一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)三者不可兼得,必须进行权衡选择。在实际应用中,这意味着系统设计者需要根据业务需求来选择适当的平衡点,例如在强一致性需求较高的场景下,可能需要牺牲一部分可用性。Spring的。

weixin_42452924的博客 963

Spring Boot + MyBatis + Druid + Atomikos 多数据源分布式事务项目教程

Spring Boot + MyBatis + Druid + Atomikos 多数据源分布式事务项目教程 1. 项目介绍 本项目基于 Spring Boot、MyBatis、Druid 和 Atomikos,旨在配置动态多数据源并实现分布式事务。通过该项目,开发者可以轻松地在 Spring Boot 应用中集成多数据源,并确保在分布式环境下的数据一致性。 主要特性 动态多数据源切换:支持在运...

gitblog_00363的博客 1089

spring+druid+AtomikosDataSource实现多数据源切换及分布式事务控制

spring+druid+AtomikosDataSource实现多数据源切换及分布式事务控制

【SpringBoot框架篇】4.集成jta-atomikos实现分布式事务

springboot集成jta-atomikos实现分布式事务简介引入依赖修改配置文件添加配置读取类创建多数据源,管理事务数据持久化数据库DLL文件模拟事务回滚 简介 1.分布式事务 说到分布式事务,可以理解为,由于分布式而引起的事务不一致的问题。随着项目做大,模块拆分,数据库拆分。一次包含增删改操作数据库涉及到了更新两个不同物理节点的数据库,这样的数据库事务只能保证自己处理的部分的事务,但是整个...

皓亮君的博客 6125

麒麟操作系统Kylin如何从 2203 升级到 2403

fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;开始升级流程第一步:升级前准备1. 确认版本为 V10 SP1 22032. 备份全部重要数据3. 确保网络稳定4. 关闭应用第二步:选择升级方式方法一:图形界面升级方法二:命令行升级1. 更新现有系统至最新2. 启动“系统升级”工具3. 检测并开始下载2403。

让编程变的很简单!! 2655

手机抽奖页面代码html,html5大转盘抽奖支持手机转盘抽奖代码

特效描述:html5 大转盘抽奖 支持手机 转盘抽奖代码。html5转盘,html5抽奖,手机转盘,手机抽奖,手机转盘抽奖,可配置奖品抽奖。代码结构1. 引入CSS2. 引入JS3. HTML代码大转盘活动var turnplate={restaraunts:[],//大转盘奖品名称colors:[],//大转盘奖品区块对应背景颜色outsideRadius:192,//大转盘外圆的半径textR...

weixin_39628551的博客 1861

spring+atomikos+druid分布式事务

       在工作中遇到了分布式事务问题,当时遇到的问题是多数据源下添加事务,无法切换数据源。后来通过查找资料了解到一般事务都会添加在service层,如果使用spring的声明式事物管理,那么在调用service层代码之前,spring会通过aop的方式动态添加事务控制代码,所以如果要想保证事物是有效的,那么必须spring添加事务之前把数据源动态切换过来,也就是动态切换数据源的aop要至少在...

ZZY的博客 1092

ESP32S3编译micropython固件

编译ESP32芯片的micropython固件

m0_73253860的博客 2553

探索分布式事务的利器:springboot-mybatis-druid-atomikos

探索分布式事务的利器:springboot-mybatis-druid-atomikos 项目介绍 在现代微服务架构中,分布式事务管理是一个不可忽视的挑战。为了应对这一挑战,我们推出了 springboot-mybatis-druid-atomikos 项目。该项目基于 Spring Boot、MyBatis、Druid 和 Atomikos,旨在提供一个高效、可靠的解决方案,帮助开发者轻松实现动...

gitblog_00205的博客 532

VAY 是 SAP 自动科目确定(OBYC-GBB)中的科目修改码,专用于带科目分配对象的销售订单发货场景,核心是触发 “Dr 成本要素科目(如销售费用 / 特定成本对象) Cr 库存商品” 的分录,

摘要:VAY是SAP中用于带科目分配对象(如成本中心、WBS)的销售订单发货的科目修改码,与标准VAX场景不同,它生成"借成本要素科目/贷库存商品"的分录。配置路径为OBYC-GBB-VAY,需确保借方科目为成本要素。典型业务场景包括免费样品、项目专用发货等。常见问题包括VAY未触发或科目记账错误,需检查销售订单科目分配、移动类型设置及OBYC配置。特殊场景建议单独配置科目以便费用分析。

金牌架构师 1253

Proteus-51单片机-LCD1602显示DS1302时钟

本文详细介绍了如何使用Proteus仿真51单片机配合LCD1602显示DS1302时钟的步骤,包括DS1302时钟芯片的主要特性、引脚定义、外围电路以及LCD1602的原理和技术参数。此外,还讲解了LCD1602的指令集和显示字符的方法,并给出了初始化及显示操作的步骤。

让你爱上电路设计 6978

【十九】Spring Boot之分布式事务(JTA、Atomikos、Druid、Mybatis)

一、介绍 1.分布式、本地事务 1.本地事务:普通事务。只能保证在一个数据库上的操作ACID。 JDBC事务就是本地事务,通过connection对象管理。 2.分布式事务:两个及以上数据库源的事务(由每台数据库的本地事务组成的), 使事务可以跨越多个数据库。比如,A库的a1表和B库的b1表,在一个事务中,如果B库的b1表回滚了,A库的a1表也要回滚。 JTA事务支持分布式事务。JTA指Ja...

很多时候犯错都是在不知情的情况下发生的 497

《嵌入式最全面试题-Offer直通车》目录

嵌入式领域蓬勃发展,嵌入式工程师成为众多科技企业争抢的热门人才。如果你渴望在嵌入式面试中脱颖而出,成功斩获心仪的 offer,那么《嵌入式最全面试题 - Offer直通车》将是你的绝佳选择。本专栏是优快云是热门专栏,100多篇文章,总字数过百万。每月新增订阅用户过百,现在是优惠价9.9元,后面要逐渐恢复原价,早订阅早受益。本专栏精心整理了众多超万字的精华内容,总计达数十万字的嵌入式面试题总结。涵盖从嵌入式基础知识到各大厂面试真题,从驱动开发到操作系统,从硬件到软件等各个方面。

大模型大数据攻城狮的专栏 8389

Spring-boot + atomikos + druid分布式事务配置

Spring-boot + atomikos + druid分布式事务配置1.额外依赖项 javax.transaction jta 1.1 com.atomikos transactions-jta 4.0.4 com.atomikos transactions-jdbc 4.0.4

imthrall的专栏 3187

如何在 R 中执行 Kruskal-Wallis 检验

Kruskal-Wallis 检验用于确定三个或更多独立组的中位数之间是否存在统计学上的显着差异。它被认为是单向方差分析的非参数等效项。本教程介绍了如何在 R 中执行 Kruskal-Wallis 检验。示例:R 中的 Kruskal-Wallis 检验 假设研究人员想知道三种不同的肥料是否会导致不同水平的植物生长。他们随机选择 30 种不同的植物并将它们分成三组,每组 10 株,每组施用不同的肥料。在一个月结束时,他们测量每株植物的高度。使用以下步骤执行 Kruskal-Wallis 检验以确定三个组的中

Mrrunsen的博客 3796

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: 分布式事务中使用RocketMQ的事务消息机制优化事务的处理逻辑
下一篇: Elasticsearch索引的基本操作(5)-别名设置
冯立彬
冯立彬 优质创作者: 编程框架技术领域 优质创作者: 编程框架技术领域
博客等级 码龄21年 5458粉丝 593原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值