开发传统应用遇到的最大问题就是多数据源的事务一致性问题, 下面介绍一种常用的分布式事务处理方式的使用
开发环境:Eclipse+Java1.7 + tomcat7, 另外使用到的开源框架 Spring3.X
提到分布式事务大家首先想到的肯定是jta,我们用到的就是基于jta的一种实现atomikos,下面就介绍一下他的使用
1、 依赖的jar
<!--atomikos 分布式事务依赖 --> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jta</artifactId> <version>${atomikos.version}</version> <optional>true</optional> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jdbc</artifactId> <version>${atomikos.version}</version> <optional>true</optional> </dependency> <dependency> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> <version>${jta.version}</version> <optional>true</optional> </dependency> <!--数据源的连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency>
2、 配置数据源
数据源连接池,必须是支持XA标准的连接池,什么是XA标准呢?
XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。
以下的函数使事务管理器可以对资源管理器进行的操作:
1)xa_open,xa_close:建立和关闭与资源管理器的连接。
2)xa_start,xa_end:开始和结束一个本地事务。
3)xa_prepare,xa_commit,xa_rollback:预提交、提交和回滚一个本地事务。
4)xa_recover:回滚一个已进行预提交的事务。
5)ax_开头的函数使资源管理器可以动态地在事务管理器中进行注册,并可以对XID(TRANSACTION IDS)进行操作。
6)ax_reg,ax_unreg;允许一个资源管理器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或撤消注册。
<!--dataSource--> <bean id="dataSource1" class="com.alibaba.druid.pool.xa.DruidXADataSource" init-method="init" destroy-method="close"> <!-- 基本属性 url、user、password --> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${jdbc.initialSize}" /> <property name="minIdle" value="${jdbc.minIdle}" /> <property name="maxIdle" value="${jdbc.maxIdle}" /> <property name="maxActive" value="${jdbc.maxActive}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="${jdbc.maxWait}"/> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${jdbc.validationQuery}" /> <property name="testWhileIdle" value="${jdbc.testWhileIdle}" /> <property name="testOnBorrow" value="${jdbc.testOnBorrow}" /> <property name="testOnReturn" value="${jdbc.testOnReturn}" /> <property name="filters" value="${jdbc.filters}" /> </bean> <bean id="dataSource2" class="com.alibaba.druid.pool.xa.DruidXADataSource" init-method="init" destroy-method="close"> <!-- 基本属性 url、user、password --> <property name="url" value="${jdbc1.url}" /> <property name="username" value="${jdbc1.username}" /> <property name="password" value="${jdbc1.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${jdbc.initialSize}" /> <property name="minIdle" value="${jdbc.minIdle}" /> <property name="maxIdle" value="${jdbc.maxIdle}" /> <property name="maxActive" value="${jdbc.maxActive}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="${jdbc.maxWait}"/> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${jdbc.validationQuery}" /> <property name="testWhileIdle" value="${jdbc.testWhileIdle}" /> <property name="testOnBorrow" value="${jdbc.testOnBorrow}" /> <property name="testOnReturn" value="${jdbc.testOnReturn}" /> <property name="filters" value="${jdbc.filters}" /> </bean>
3、强数据源指定到AtomikosDataSourceBean中,再有该类的对象向DAO层提供数据源服务
配置如下
datasource1
<bean id="xaDataSource1" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close"> <property name="xaDataSource" ref="dataSource1"/> <property name="uniqueResourceName" value="dataSource1"/> <property name="xaDataSourceClassName" value="com.alibaba.druid.pool.xa.DruidXADataSource"/> <property name="xaProperties"> <props> <prop key="serverName">test</prop> <prop key="portNumber">test</prop> <prop key="databaseName">test</prop> <prop key="user">test</prop> <prop key="password">test</prop> </props> </property> </bean>
dataSource2
<bean id="xaDataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close"> <property name="xaDataSource" ref="dataSource2"/> <property name="uniqueResourceName" value="dataSource2"/> <property name="xaDataSourceClassName" value="com.alibaba.druid.pool.xa.DruidXADataSource"/> <property name="xaProperties"> <props> <prop key="serverName">test</prop> <prop key="portNumber">test</prop> <prop key="databaseName">test</prop> <prop key="user">test</prop> <prop key="password">test</prop> </props> </property> </bean>
3、将数据源托管到TranscationManager
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <description>UserTransactionImp</description> <property name="transactionTimeout" value="300"/> </bean> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <description>UserTransactionManager</description> <property name="forceShutdown"> <value>true</value> </property> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <description>JtaTransactionManager</description> <property name="transactionManager"> <ref bean="atomikosTransactionManager" /> </property> <property name="userTransaction"> <ref bean="atomikosUserTransaction" /> </property> <property name="allowCustomIsolationLevels" value="true"/> </bean>
4、定义切面
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="do*" propagation="REQUIRED" rollback-for="Throwable, Exception, RuntimeException" /> <tx:method name="query*" propagation="NOT_SUPPORTED" /> <tx:method name="load*" propagation="NOT_SUPPORTED" /> <tx:method name="find*" propagation="NOT_SUPPORTED" /> <tx:method name="*" read-only="true" propagation="SUPPORTS" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* com.jl.net..service.*.*(..))" id="pointCut" /> <aop:advisor pointcut-ref="pointCut" advice-ref="txAdvice" /> <aop:aspect ref="serviceInterceptor" order="2"> <aop:around method="doAround" pointcut-ref="pointCut" /> </aop:aspect> </aop:config>
5、 jta.properties (路径跟log4j.properties一致就好)
这个文件不配置系统也能启动,因为有默认配置,个人建议配置一下。详细配置
com.atomikos.icatch.console_file_name = xam.out
com.atomikos.icatch.log_base_name = xamlog.log
com.atomikos.icatch.service = com.atomikos.icatch.standalone.UserTransactionServiceFactory
相关推荐
1. 基于Aspectj实现动态数据源...6. 实现事务内切换数据源(支持原生Spring声明式事务哟,仅此一家),并支持多数据源事务回滚(有了它除了跨服务的事务你需要考虑分布式事务,其他都不需要,极大的减少了系统的复杂程度)
Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供...
Spring(IOC DI 声明式事务处理) SpringMVC(支持Restful风格) Hibernate Validate(参数校验) Mybatis(最少配置方案) Quartz时间调度 Redis缓存(ProtoStuff序列化) Redis Sentinel主从高可用方案 Druid...
1.面向切面编程提供声明式事务管理 2.spring支持用户自定义的切面 面向切面编程(aop)是对面向对象编程(oop)的补充, 面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。 ...
4.2.2 分布式事务处理、XA规范和 2PC协议 192 4.2.3 使用JTA全局事务保证多 数据库的一致性 193 4.3 事务隔离、传播属性的设置 198 4.3.1 并发访问和隔离 198 4.3.2 事务属性 199 4.4 EJB的事务管理 201 4.4.1 容器...
- 熟练掌握 Spring 框架,包括 IOC 和 DI、AOP 编程、声明式事务处理及 SSH 的整合等技术。 7. Mybatis 和 SpringMVC 框架: - 熟悉 Mybatis 和 SpringMVC 开源框架。 8. 数据库技能: - 熟悉 Oracle 和 MySQL ...
* 熟练掌握 Spring 框架,包括 IOC 和 DI、AOP 编程、声明式事务处理及 SSH 的整合等技术 * 熟悉 Mybatis、SpringMVC 开源框架 数据库技能 * 熟悉 Oracle、MySQL 数据库 * 能够进行简单的 PL/SQL 开发 * 了解 ...
leetcode题库 Fashion's Blog - 持续更新中... 多线程与高并发 JVM 运行时数据区 垃圾回收 类加载过程 ...事务 ...分布式锁 ...基于Reactive完成分布式锁 ...全手写基于Netty的RPC框架自定义协议,连接池 ...Feign声明式R
CMT DEMO(容器管理事务演示) 事务隔离性的一些基础知识 在组件之间实现事务和异步提交事务(NET2.0) 其它 在.NET访问MySql数据库时的几点经验! 自动代码生成器 关于能自定义格式的、支持多语言的、支持多数据库的...