分布式事务系列(4.1)Atomikos的分布式案例

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

1 系列目录

2 Atomikos使用非XA数据库驱动实现分布式事务

项目地址见:Atomikos使用非XA数据库驱动实现分布式事务

2.1 业务逻辑的操作

UserDao和LogDao,操作分别如下:

@Repository
public class UserDao {

    @Resource(name="jdbcTemplateA")
    private JdbcTemplate jdbcTemplate;

    public void save(User user){
        jdbcTemplate.update("insert into user(name,age) values(?,?)",user.getName(),user.getAge());
    }
}

@Repository
public class LogDao {

    @Resource(name="jdbcTemplateB")
    private JdbcTemplate jdbcTemplate;

    public void save(User user){
        jdbcTemplate.update("insert into log(name,age) values(?,?)",user.getName(),user.getAge());
    }
}

即上述两个JdbcTemplate使用不同的数据库。

UserService综合上述两个业务操作,使它们处于同一个事务中:

@Service
public class UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private LogDao logDao;

    @Transactional
    public void save(User user){
        userDao.save(user);
        logDao.save(user);
        throw new RuntimeException();
    }
}

2.2 配置

上述业务代码我们看不到分布式事务的存在,这种正是我们想要的效果,分布式事务对业务透明。到底是如何来实现呢?

2.2.1 dataSource和JdbcTemplate配置

<bean id="dataSourceA" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" init-method="init"  destroy-method="close">
    <property name="uniqueResourceName" value="XA1DBMS" />  

       <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8" /> 
       <property name="user" value="root" /> 
       <property name="password" value="xxxx" /> 
       <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 

    <property name="poolSize" value="3" />  
    <property name="minPoolSize" value="3" />  
    <property name="maxPoolSize" value="5" />
</bean>

<bean id="dataSourceB" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" init-method="init" destroy-method="close">   
    <property name="uniqueResourceName" value="XA2DBMS" />  

    <property name="url" value="jdbc:mysql://localhost:3306/test2?useUnicode=true&amp;characterEncoding=utf-8" /> 
       <property name="user" value="root" /> 
       <property name="password" value="xxxx" /> 
       <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 

    <property name="poolSize" value="3" />  
    <property name="minPoolSize" value="3" />  
    <property name="maxPoolSize" value="5" /> 
</bean>

<bean id="jdbcTemplateA" class="org.springframework.jdbc.core.JdbcTemplate">  
    <property name="dataSource" ref="dataSourceA" />  
</bean>  

<bean id="jdbcTemplateB" class="org.springframework.jdbc.core.JdbcTemplate">  
    <property name="dataSource" ref="dataSourceB" />  
</bean>

自行配置2个数据库地址

我们平常使用的dataSource,大部分是c3p0、dbcp等,这里就不能使用它们了,需要换成可以模拟XA协议的dataSource,这里即AtomikosNonXADataSourceBean。

2.2.2 事务配置

我们知道分布式事务中需要一个事务管理器即接口javax.transaction.TransactionManager、面向开发人员的javax.transaction.UserTransaction。对于Atomikos来说分别对应如下:

  • com.atomikos.icatch.jta.UserTransactionImp
  • com.atomikos.icatch.jta.UserTransactionManager

我们如果想使用分布式事务的同时,又想使用Spring带给我们的@Transactional便利,就需要配置一个JtaTransactionManager,而该JtaTransactionManager是需要一个userTransaction实例的

<bean id="userTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">  
    <property name="transactionTimeout" value="300" />  
</bean>  

<bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
    <property name="userTransaction" ref="userTransaction" />   
</bean>

<tx:annotation-driven transaction-manager="springTransactionManager"/>

可以对比下jotm的案例配置jotm的分布式事务配置。可以看到jotm中使用的xapool中的StandardXADataSource是需要一个transactionManager的,而Atomikos使用的AtomikosNonXADataSourceBean则不需要。我们知道,StandardXADataSource中有了transactionManager就可以获取当前线程的事务,同时把XAResource加入进当前事务中去,而AtomikosNonXADataSourceBean却没有,它是怎么把XAResource加入进当前线程绑定的事务呢?这时候就需要可以通过静态方法随时获取当前线程绑定的事务。

2.2.3 jar包依赖

这里只使用了Atomikos,不像jotm还使用了xapool。

<!-- atomikos -->
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jdbc</artifactId>
    <version>4.0.0M4</version>
</dependency>

3 Atomikos使用XA数据库驱动实现分布式事务

项目地址见:Atomikos使用非XA数据库驱动实现分布式事务

3.1 业务逻辑的操作

UserDao和LogDao,操作分别如下:

@Repository
public class UserDao {

    @Resource(name="jdbcTemplateA")
    private JdbcTemplate jdbcTemplate;

    public void save(User user){
        jdbcTemplate.update("insert into user(name,age) values(?,?)",user.getName(),user.getAge());
    }
}

@Repository
public class LogDao {

    @Resource(name="jdbcTemplateB")
    private JdbcTemplate jdbcTemplate;

    public void save(User user){
        jdbcTemplate.update("insert into log(name,age) values(?,?)",user.getName(),user.getAge());
    }
}

即上述两个JdbcTemplate使用不同的数据库。

UserService综合上述两个业务操作,使它们处于同一个事务中:

@Service
public class UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private LogDao logDao;

    @Transactional
    public void save(User user){
        userDao.save(user);
        logDao.save(user);
        throw new RuntimeException();
    }
}

3.2 配置

上述业务代码我们看不到分布式事务的存在,这种正是我们想要的效果,分布式事务对业务透明。到底是如何来实现呢?

3.2.1 dataSource和JdbcTemplate配置

<bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
    <property name="uniqueResourceName" value="XA1DBMS" />  
    <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />  
    <property name="xaProperties">  
        <props>  
            <prop key="URL">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8</prop>  
            <prop key="user">root</prop>  
            <prop key="password">ligang</prop>  
        </props>  
    </property>  
    <property name="poolSize" value="3" />  
    <property name="minPoolSize" value="3" />  
    <property name="maxPoolSize" value="5" />
</bean>

<bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">   
    <property name="uniqueResourceName" value="XA2DBMS" />  
    <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />  
    <property name="xaProperties">  
        <props>  
            <prop key="URL">jdbc:mysql://localhost:3306/test2?useUnicode=true&amp;characterEncoding=utf-8</prop>  
            <prop key="user">root</prop>  
            <prop key="password">ligang</prop>  
        </props>  
    </property>  
    <property name="poolSize" value="3" />  
    <property name="minPoolSize" value="3" />  
    <property name="maxPoolSize" value="5" /> 
</bean>

自行配置上述2个数据库地址

我们平常使用的dataSource,大部分是c3p0、dbcp等,这里就不能使用它们了,需要换成可以Atomikos自己的dataSource,这里即AtomikosDataSourceBean。它需要使用支持XA的jdbc驱动。具体就是需要一个xaDataSourceClassName,我们这里使用的是mysql支持xa的的MysqlXADataSource,它实现了javax.sql.XADataSource接口,即可以产生XAConnection连接。

Atomikos使用非XA数据库驱动实现分布式事务 与 Atomikos使用XA数据库驱动实现分布式事务唯一配置上的不同就是这里的dataSource配置,其他内容都一样。

3.2.2 事务配置

我们知道分布式事务中需要一个事务管理器即接口javax.transaction.TransactionManager、面向开发人员的javax.transaction.UserTransaction。对于Atomikos来说分别对应如下:

  • com.atomikos.icatch.jta.UserTransactionImp
  • com.atomikos.icatch.jta.UserTransactionManager

我们如果想使用分布式事务的同时,又想使用Spring带给我们的@Transactional便利,就需要配置一个JtaTransactionManager,而该JtaTransactionManager是需要一个userTransaction实例的

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">  
    <property name="transactionTimeout" value="300" />  
</bean>  

<bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
    <property name="userTransaction" ref="atomikosUserTransaction" />   
</bean>

<tx:annotation-driven transaction-manager="springTransactionManager"/>

3.2.3 jar包依赖

这里只使用了Atomikos,不像jotm还使用了xapool。

<!-- atomikos -->
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jdbc</artifactId>
    <version>4.0.0M4</version>
</dependency>

4 结束语

本文介绍了Atomikos使用XA数据库驱动和非XA数据库驱动两种方式来实现分布式事务的案例,下一篇文章就来详细说明下其中的原理。

  • 在Atomikos中,2PC的中的协调者是谁?参与者又是谁?
  • 在XA数据库驱动和非XA数据库驱动两种情况下,事务是怎么开启的?当执行业务操作的时候,参与者又是怎么加入事务中的呢?2PC的过程又是怎么进行的?事务是怎么回滚的?事务是怎么提交的呢?
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
22天前
|
存储 监控 固态存储
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN 分布式存储虚拟化平台VMDK文件1KB问题数据恢复案例
在一例vSAN分布式存储故障中,因替换故障闪存盘后磁盘组失效,一台采用RAID0策略且未使用置备的虚拟机VMDK文件受损,仅余1KB大小。经分析发现,该VMDK文件与内部虚拟对象关联失效导致。恢复方案包括定位虚拟对象及组件的具体物理位置,解析分配空间,并手动重组RAID0结构以恢复数据。此案例强调了深入理解vSAN分布式存储机制的重要性,以及定制化数据恢复方案的有效性。
48 5
|
24天前
|
存储 NoSQL Java
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这篇文章是关于Java面试中的分布式架构问题的笔记,包括分布式架构下的Session共享方案、RPC和RMI的理解、分布式ID生成方案、分布式锁解决方案以及分布式事务解决方案。
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
|
4月前
|
存储 分布式计算 监控
Hadoop【基础知识 01+02】【分布式文件系统HDFS设计原理+特点+存储原理】(部分图片来源于网络)【分布式计算框架MapReduce核心概念+编程模型+combiner&partitioner+词频统计案例解析与进阶+作业的生命周期】(图片来源于网络)
【4月更文挑战第3天】【分布式文件系统HDFS设计原理+特点+存储原理】(部分图片来源于网络)【分布式计算框架MapReduce核心概念+编程模型+combiner&partitioner+词频统计案例解析与进阶+作业的生命周期】(图片来源于网络)
252 2
|
22天前
|
存储 固态存储 虚拟化
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN ESXi超融合HCI分布式存储数据恢复案例
近期,我司处理了一个由10台华为OceanStor存储组成的vSAN超融合架构,其中一台存储闪存盘出现故障,用户取下后用新的闪存盘代替,然后对该闪存盘所在的磁盘组进行重建,导致集群中一台使用0置备策略的虚拟机数据丢失。
39 6
|
2月前
|
消息中间件
分布式篇问题之通过本地消息表实现分布式事务的最终一致性问题如何解决
分布式篇问题之通过本地消息表实现分布式事务的最终一致性问题如何解决
|
2月前
|
消息中间件 Java 中间件
Java面试题:解释分布式事务的概念,讨论常见的分布式事务解决方案。
Java面试题:解释分布式事务的概念,讨论常见的分布式事务解决方案。
34 0
|
3月前
|
缓存 NoSQL 数据库
分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)
分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)
81 0
|
4月前
|
消息中间件 大数据 分布式数据库
分布式事务:构建可靠分布式系统的基石
【4月更文挑战第21天】分布式事务是确保现代分布式系统数据一致性和完整性的关键技术,涉及多服务协调,面临网络延迟、故障和数据一致性等问题。本文探讨了分布式事务的原理,包括两阶段提交、三阶段提交、分布式锁和补偿机制等解决方案,并阐述其在微服务、分布式数据库和消息队列等场景的应用。面对挑战,我们需要持续优化分布式事务处理机制。
|
4月前
|
存储 NoSQL Java
分布式锁,Redission,其它实现问题讲解,以及面试题回答案例
分布式锁,Redission,其它实现问题讲解,以及面试题回答案例
173 1
|
4月前
|
分布式计算 监控 Hadoop
Hadoop【基础知识 02】【分布式计算框架MapReduce核心概念+编程模型+combiner&partitioner+词频统计案例解析与进阶+作业的生命周期】(图片来源于网络)
【4月更文挑战第3天】Hadoop【基础知识 02】【分布式计算框架MapReduce核心概念+编程模型+combiner&partitioner+词频统计案例解析与进阶+作业的生命周期】(图片来源于网络)
212 0
下一篇
DDNS