spring分布式事务学习笔记(1)
此文已由作者夏昀授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
分布式事务对性能有一定的影响,所以不是最佳的解决方案,能通过设计避免最好尽量避免。
分布式事务(Distributed transactions),也称作XA事务(XA是一个协议的名字),在spring中被称作global transaction,是指一个事务会涉及到不同的事务资源,比如不同的数据库,消息队列。事务资源都支持commit和rollback这样的事务控制命令。
按是否需要实现完整javaEE功能的应用服务器,可以将实现XA事务的方法分为两种:
1.一般情况下,XA事务是通过javaEE应用服务器实现的,即CMT(Container Managed Transaction)。应用服务器实现了JTA(Java Transaction API),应用通过JNDI获取应用服务器的JTA UserTransaction。JTA的api比较复杂,开发者需要研究较多JTA的细节,使用spring事务管理可以简化JTA的编程模型。但是这样还是需要依赖实现了对应javaEE功能的应用服务器。
2.不需要应用服务器(standalone),或者只需要轻量级的应用服务器,例如tomcat,tomcat没有实现所有的javaEE功能。在应用中加上支持jta的第三方包,例如atomikos,JOTM等。
分布式事务的结构如图所示:
图中,1表示APP与资源管理器RM之间的接口,是资源管理器的本地接口或者XA接口。如果使用事务管理器TM来管理分布式事务, 则不需要app直接调用rm,即1接口不会使用。 2表示app与TM的接口,即UserTransaction,这个接口和普通的事务管理接口类似,是一个有提交和回滚等操作的接口。使用该接口,就像事务只处理一个数据源一样。app通过该接口控制事务的提交或回滚。 3是TM与RM之间的接口,是一个两阶段提交(2 phase commit)的过程,两阶段提交简单的说就是一个数据源的事务要提交两次才算真正提交。该操作由TM控制,app不直接调用接口3。
下面通过一个demo介绍如何使用spring+mybatis+atomikos+tomcat构建在一个事务中涉及两个数据源的web应用。
demo功能:实现一个能成功提交和回滚的涉及两个数据库数据源的XA事务。
demo将实现:
1.一次性在两个数据库的两张表中各插入一条数据并提交。
2.一次性在两个数据库的两张表中各插入一条数据并回滚。
测试方式:restful web api
使用工具:
spring 4.1.1.RELEASE
mybatis 3.2.7
atomikos 3.7.0
tomcat 7
在mysql中建立两个schema,分别为dev和qa。并在里面分别建立一张名字表。
schema:dev
table:namaDev
id | nameDev
scheme:qa
table:nameQa
id | nameQa
对应的sql为
CREATE SCHEMA `qa` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;CREATE SCHEMA `dev` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; CREATE TABLE `dev`.`nameDev` ( `id` BIGINT NOT NULL AUTO_INCREMENT , `nameDev` VARCHAR(45) NULL , PRIMARY KEY (`id`) , UNIQUE INDEX `id_UNIQUE` (`id` ASC) );
CREATE TABLE `qa`.`nameQa` ( `id` BIGINT NOT NULL AUTO_INCREMENT , `nameQa` VARCHAR(45) NULL , PRIMARY KEY (`id`) , UNIQUE INDEX `id_UNIQUE` (`id` ASC) );
代码分析:
本项目使用spring框架,因此首先配置相关bean
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
4 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
5 xmlns:rabbit="http://www.springframework.org/schema/rabbit"
6 xmlns:cache="http://www.springframework.org/schema/cache" xmlns:task="http://www.springframework.org/schema/task"
7 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
8 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
9 <context:component-scan base-package="com.xy">
10 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
11 </context:component-scan>
12 <context:property-placeholder location="classpath:context/database.properties"/>
13 <tx:annotation-driven/>
14
15 <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init"
16 destroy-method="close" abstract="true">
17 <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
18 <property name="poolSize" value="10" />
19 <property name="minPoolSize" value="10"/>
20 <property name="maxPoolSize" value="30"/>
21 <property name="borrowConnectionTimeout" value="60"/>
22 <property name="reapTimeout" value="20"/>
23 <!-- 最大空闲时间 -->
24 <property name="maxIdleTime" value="60"/>
25 <property name="maintenanceInterval" value="60"/>
26 <property name="loginTimeout" value="60"/>
27 <property name="testQuery">
28 <value>select 1</value>
29 </property>
30 </bean>
31
32 <bean id="qadataSource" parent="abstractXADataSource">
33 <!-- value只要两个数据源不同就行,随便取名 -->
34 <property name="uniqueResourceName" value="mysql/sitestone1" />
35 <property name="xaDataSourceClassName"
36 value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
37 <property name="xaProperties">
38 <props>
39 <prop key="URL">${qa.db.url}</prop>
40 <prop key="user">${qa.db.user}</prop>
41 <prop key="password">${qa.db.password}</prop>
42 <prop key="pinGlobalTxToPhysicalConnection">true</prop>
43 </props>
44 </property>
45 </bean>
46
47 <bean id="devdataSource" parent="abstractXADataSource">
48 <!-- value只要两个数据源不同就行,随便取名 -->
49 <property name="uniqueResourceName" value="mysql/sitestone" />
50 <property name="xaDataSourceClassName"
51 value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
52 <property name="xaProperties">
53 <props>
54 <prop key="URL">${dev.db.url}</prop>
55 <prop key="user">${dev.db.user}</prop>
56 <prop key="password">${dev.db.password}</prop>
57 <prop key="pinGlobalTxToPhysicalConnection">true</prop>
58 </props>
59 </property>
60 </bean>
61
62
63
64 <bean id="qasqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
65 <property name="dataSource" ref="qadataSource" />
66 <property name="mapperLocations" value="classpath*:com/xy/dao/*.xml" />
67 </bean>
68
69 <bean id="devsqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
70 <property name="dataSource" ref="devdataSource" />
71 <property name="mapperLocations" value="classpath*:com/xy/daodev/*.xml" />
72 </bean>
73
74 <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
75 init-method="init" destroy-method="close">
76 <property name="forceShutdown">
77 <value>true</value>
78 </property>
79 </bean>
80 <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
81 <property name="transactionTimeout" value="300" />
82 </bean>
83
84 <bean id="transactionManager"
85 class="org.springframework.transaction.jta.JtaTransactionManager">
86 <property name="transactionManager">
87 <ref bean="atomikosTransactionManager"/>
88 </property>
89 <property name="userTransaction">
90 <ref bean="atomikosUserTransaction"/>
91 </property>
92 <!-- 必须设置,否则程序出现异常 JtaTransactionManager does not support custom isolation levels by default -->
93 <property name="allowCustomIsolationLevels" value="true"/>
94
95 </bean>
96
97
98
99 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">100 <property name="basePackage" value="com.xy.dao"/>101 <property name="sqlSessionFactoryBeanName" value="qasqlSessionFactory" />102 </bean>103
104 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">105 <property name="basePackage" value="com.xy.daodev"/>106 <property name="sqlSessionFactoryBeanName" value="devsqlSessionFactory" />107 </bean>108 </beans>
其中qadataSource和devdataSource是对应两个数据库的数据源,qasqlSessionFactory和devsqlSessionFactory是mybatis的sessionfactory,两个MapperScannerConfigurer自动将不同数据源的sql语句文件与interface自动装配起来,atomikosTransactionManager会自动管理两个atomikos的数据源的事务,即resource manager,atomikosUserTransaction为最上层的事务管理器为transaction manager。
网易云免费体验馆,0成本体验20+款云产品!
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 MySQL之不得不说的keepsync和trysync
spring分布式事务学习笔记(1)的更多相关文章
- spring分布式事务学习笔记
最近项目中使用了分布式事务,本文及接下来两篇文章总结一下在项目中学到的知识. 分布式事务对性能有一定的影响,所以不是最佳的解决方案,能通过设计避免最好尽量避免. 分布式事务(Distributed t ...
- spring分布式事务学习笔记(2)
此文已由作者夏昀授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Model类如下:package com.xy.model 1 package com.xy.model; ...
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点
Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...
- spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)
绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...
- Spring分布式事务实现概览
分布式事务,一直是实现分布式系统过程中最大的挑战.在只有单个数据源的单服务系统当中,只要这个数据源支持事务,例如大部分关系型数据库,和一些MQ服务,如activeMQ等,我们就可以很容易的实现事务. ...
- Spring分布式事务
[如何实现XA式.非XA式Spring分布式事务] [http://www.importnew.com/15812.html] 在JavaWorld大会上,来自SpringSource的David S ...
- Mysql事务学习笔记
Mysql事务学习笔记 1.事务概述 事务是数据库的执行单元,它包含了一条或多条sql语句,进行的操作是要么全部执行,要么全部都不执行. 2.事务执行命令 语法格式: start transactio ...
随机推荐
- Mysql 数据库允许远程连接 服务器连接错误 Host 'XXX' is not allowed to connect to this MySQL server
如果连接数据库的时候出现这个问题 Host 'XXX' is not allowed to connect to this MySQL server 说明 Mysql数据库 不允许远程连接, 需要修改 ...
- 使用nginx代理weblogic负载方案
之前一直用apache来做weblogic的前端,由于nginx对静态内容的出色性能,不得不转投nginx.这里就不 再写weblogic的安装了. 安装nginx nginx需要pcre做支持,一般 ...
- Gerrit实现代码审计(code review)
1.Gerrit是个啥? 实现代码审计,比git(gitlab.github)多了代码审计的功能. 2.两类角色 角色1:我是代码编写者,只能写代码和提交给审计者代码,不能直接把代码合并到线上发布 角 ...
- javascript array-like object
http://www.nfriedly.com/techblog/2009/06/advanced-javascript-objects-arrays-and-array-like-objects/ ...
- protobuf 之 MessageLite 接口摘录
class LIBPROTOBUF_EXPORT MessageLite { public: inline MessageLite() {} virtual ~MessageLite(); // Ba ...
- NoSQL之Redis探析
下载地址:wget http://download.redis.io/releases/redis-2.8.8.tar.gz安装steps:1 下载Official Website : http:// ...
- 硬件开发之pcb---PCB抗干扰设计原则
一 电源线布置: 1.电源线.地线的走向应与资料的传递方向一致. 二 地线布置: 1.数字地与模拟地分开. 2.接地线应尽量加粗,致少能通过3倍于印制板上的允许电流,一般应达2~3mm. 3.接地线应 ...
- Java 文件路径的读取
记得在操作系统中了解到文件读取有两种方式,当然这在各编程语言中也是通用的,所以java路径也分,相对和绝对路径. 绝对路径 绝对路径URI ,听着和URL非常相似.那我们就来看看吧. URI(Unif ...
- Sql数据库查询语言
1.概述 Sql是一种面向数据库的结构化查询语言.是符合美国国家标准化组织ANSI的一种计算机标准语言. Sql具对数据库的操作有:增删改查.创建数据库.创建表.创建存储过程.创建视图等 RDBMS关 ...
- 包管理 import debug 模块管理 module
import sys, os this_file_abspath = os.path.dirname(os.path.abspath(__file__)) ProjectUtil_path = '{} ...