代码编织梦想

一、举例说明分布式事务

在上一节代码的的Service层做一下测试,人为制造一个被除数为0的异常。然后对该服务对应的Controller方法发送请求。(postman)

@Resource
private JdbcTemplate primaryJdbcTemplate;
@Resource
private JdbcTemplate secondaryJdbcTemplate;

@Transactional
public Article saveArticle( Article article) {
    articleJDBCDAO.save(article,primaryJdbcTemplate);
    articleJDBCDAO.save(article,secondaryJdbcTemplate);
    int a = 2/0;    //人为制造一个被除数为0的异常
    return article;
}

secondaryJdbcTemplate的数据插入数据成功,primaryJdbcTemplate的数据插入数据失败。数据库事务不能跨连接, 当然也就不能跨数据源,更不能跨库。一旦出现跨连接的情况,也就成了分布式事务,事务就不能单纯依赖于数据库去处理。我们这一节的实现方式,是通过JTA来实现。

二、通过整合JTA实现分布式事务

分布式事务就是跨数据库连接的事务。一个事务的数据库操作,要么都成功,要么都失败回滚。后面我们专门做一个章节讲解事务与分布式事务。

2.1 引入maven依赖包

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

2.2 修改application配置文件

双数据源配置。删掉原有数据库连接配置.

primarydb:
  uniqueResourceName: primary
  xaDataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
  xaProperties:
    url: jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false
    user: test
    password: 4rfv$RFV
  exclusiveConnectionMode: true
  minPoolSize: 3
  maxPoolSize: 10
  testQuery: SELECT 1 from dual #由于采用HikiriCP,用于检测数据库连接是否存活。

secondarydb:
  uniqueResourceName: secondary
  xaDataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
  xaProperties:
    url: jdbc:mysql://localhost:3306/testdb2?useUnicode=true&characterEncoding=utf-8&useSSL=false
    user: test
    password: 4rfv$RFV
  exclusiveConnectionMode: true
  minPoolSize: 3
  maxPoolSize: 10
  testQuery: SELECT 1 from dual #由于采用HikiriCP,用于检测数据库连接是否存活。

MysqlXADataSource的解释:根据jdbc 4.0规范(12.2):XA数据源生成能够在全局/分布式事务中使用的XA连接。如果需要跨多个数据库或JMS调用的事务,则可能需要此类连接。您可以在此处找到有关概念的明确说明:http://www.theserverside.com/discussions/thread.tss?thread_id=21385#95346

如果不使用分布式事务,则在声明驱动程序时无需指定xa-datasource-class。这个xa-datasource-class是专门为分布式事务准备的。

2.3 数据源配置

下面是数据源bean的配置,将上面配置文件中的属性加载到Spring Bean里面。也就是将配置参数应用到我们的双数据库数据源实例对象中。

@Configuration
public class DataSourceConfig {
     //jta数据源primarydb
    @Bean(initMethod="init", destroyMethod="close", name="primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "primarydb")
    public DataSource primaryDataSource() {
         //这里是关键,返回的是AtomikosDataSourceBean,所有的配置属性也都是注入到这个类里面
        return new AtomikosDataSourceBean();
    }

    //jta数据源secondarydb
    @Bean(initMethod="init", destroyMethod="close", name="secondaryDataSource")
    @ConfigurationProperties(prefix = "secondarydb")
    public DataSource secondaryDataSource()  {
        return new AtomikosDataSourceBean();
    }

    //primaryJdbcTemplate使用primaryDataSource数据源
    @Bean
    public JdbcTemplate primaryJdbcTemplate(
                    @Qualifier("primaryDataSource") DataSource primaryDataSource) {
        return new JdbcTemplate(primaryDataSource);
    }

    //secondaryJdbcTemplate使用secondaryDataSource数据源
    @Bean
    public JdbcTemplate secondaryJdbcTemplate(
                    @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        return new JdbcTemplate(secondaryDataSource);
    }
}

2.4 事务管理器配置

负责协调多个JTA数据源实现事务机制。固定写法,不用纠结UserTransaction 、TransactionManager 、JtaTransactionManager 都是什么。或者说:都是帮我们实现JTA分布式事务的事务管理器。

@Configuration
public class TransactionManagerConfig {

    @Bean
    public UserTransaction userTransaction() throws SystemException {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(10000);
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({ "userTransaction", "atomikosTransactionManager" })
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransaction userTransaction = userTransaction();

        JtaTransactionManager manager = new JtaTransactionManager(userTransaction, atomikosTransactionManager());
        return manager;
    }
}

这时候,再测试一下文首中的测试用例:人为制造一个被除数为0的异常,异常抛出,两个数据库实例中的article表将都无法插入数据。符合事务的要求:正常情况数据操作都成功,异常情况数据操作都失败回滚。

三、JTA实现分布式事务的优缺点

优点: 能够支持分布式事务
缺点: 性能开销大,不适合用于高并发场景

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013301892/article/details/129628589

springboot+atomikos+jta实现分布式事务统一管理_安心撸码的博客-爱代码爱编程

1.要使用atomikos+jta就要引入相关依赖 <!-- automatic+jta的分布式事务管理 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter

springboot整合mybatis+jta+automatic实现分布式事务-----看这一篇包你能配置成功_dayfight_dayup的博客-爱代码爱编程

笔者在SpringBoot+Mybatis多数据源配置,以及加入事物控制博文中,已经实现了分布式事务,但是实现的是单数据源的事务的控制,设计到一个service事务要操作两个数据源,就只能控制@Primary修饰的事务管理器。 那么怎么一个数据源控制两个数据源的提交呢,MySQL是支持XA协议的,数据库驱动中也有一个com.mysql.cj.jdbc.M

springboot使用jta+atomikos分布式事务管理-爱代码爱编程

jta:Java Transaction API,即是java中对事务处理的api 即 api即是接口的意思 atomikos:Atomikos TransactionsEssentials 是一个为Java平台提供增值服务的并且开源类事务管理器 2、application.properties---->注意前缀 # Mysql 1 mys

Springboot 整合druid+mybatis+jta分布式事务+多数据源aop注解动态切换 (一篇到位)-爱代码爱编程

前言: springboot整合多数据源,大家肯定不陌生,方式不一,但是相信大家整合多数据源,如果涉及到事务,都会非常烦恼,多数据源的事务不是冲突就是失效,而如今网上千篇一律的老年博客,想找到真正解决问题的,非常少。所以我决定出来分享下可用的整合方案,而且是从头到尾的那种。 这一篇我选择的是以AOP注解的方式去进行数据源的动态切换,顺带整合jta-at

分布式事务详解——SpringBoot+Atomikos篇-爱代码爱编程

1. 分布式事务概念 讨论分布式事务之前我们分清两个概念:本地事务、分布式事务; 本地事务是解决单个数据源上的数据操作的一致性问题的话,而分布式事务则是为了解决跨越多个数据源上数据操作的一致性问题。 百度官方对分布式事务的定义是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。 也就是说我们在操作一个

SpringBoot+JPA+Atomikos实现分布式事务(前提是在SpringBoot项目中利用SpringDataJPA实现对多数据源操作时,为了避免事务报错)-爱代码爱编程

1.新建一个SpringBoot项目,向pom.xml中添加相关依赖: <!--配置数据库JPA依赖--> <dependency> <groupId>org.springframework.boot</groupId> <ar

Springboot-Sharding-Jdbc-Seata集成(五)分布式事务-爱代码爱编程

只有莲花才能比得上你的圣洁,只有月亮才能比得上你的冰清。 一.pom.xml  <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001

Springboot 整合druid+mybatis+jta分布式事务,kafka教程入门到进阶全套-爱代码爱编程

**/ @Documented @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface DataSource { String value() default DataSourceNames.ONE; } 然后是创建 DataSou

Spring Boot使用Sharding Jdbc实现分布式事务-两阶段提交-XA-爱代码爱编程

1. 引入Maven依赖 Spring Boot用的2.3.0.RELEASE版本 <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-b

shardingsphere集成springboot实现分布式事务_浅唱~幸福的博客-爱代码爱编程

1.ShardingSphere 中的分布式事务 在 ShardingSphere 中,除本地事务之外,还提供针对分布式事务的两种实现方案,分别是 XA 事务和柔性事务  具体可见官网:分布式事务 :: ShardingSphere XA 事务:XA 事务提供基于两阶段提交协议的实现机制。所谓两阶段提交,顾名思义分成两个阶段,一个是准备阶段,一个是执行

springboot集成jta-atomikos实现分布式事务_秋风未动蝉已先觉的博客-爱代码爱编程

1、依赖 <!-- jta-atomikos 分布式事务管理 --> <dependency> <groupId>org.springframework.boot</gro

springboot之jpa框架下如何使用jta——分布式事务解决方案_王者之路001的博客-爱代码爱编程

以前,笔者写过一篇博客,支付宝DTS方案,当然,只是仅仅是简单讨论了下分布式事务的解决方案。PS:笔者看了下相关评论,发现由于太简单,被不少人Diss了一通。 最近,笔者在自己的工程上,试图一次性解决分布式事务问题。 笔者自身的工程,目前是Springboot作为基本框架,以JPA作为数据库操作工作。笔者首先想到的,是如何利用现有框架,以及成熟的方案,

springboot+jta+atomic实现分布式多数据源事务管理_fromatozhappy的博客-爱代码爱编程

jta+atomic实现分布式事务数据源事务管理 atomic管理了数据源解决了在异常情况下两个数据源的回滚问题流程:   引入jar包     <!-- atomikos 分布式多数据源事务管理 -->     <dependency>          <groupId>org.springframew

spring jdbc - jta实现分布式事务-爱代码爱编程

分布式事务产生的原因 数据库事务在针对一个数据源,可以包含一个或多个数据库操作,但这些操作构成一个逻辑上的整体。 在上面的例子中,出现两个数据源,加上事务处理的注解之后发现并不能生效,两个数据库都增加了数据,至此我们发现数据库事务失效了,原因就是此时出现了分布式事务场景。 这是因为数据库事务不能跨链接,也不能跨数据源(不能跨库),只要出现以上场景