关于分布式事物 转

分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持。如果使用WAS的JTA支持,把它的属性改为WebSphere对应的TransactionManager。 
       在tomcat下,是没有分布式事务的,不过可以借助于第三方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现,在spring中分布式事务是通过jta(jotm,atomikos)来进行实现。 
1、http://jotm.objectweb.org/ 
2、http://www.atomikos.com/Main/TransactionsEssentials

一、使用JOTM例子 
(1) Dao及实现

GenericDao接口:

[java] view plaincopy

  1. public interface GenericDao {
  2. public int save(String ds, String sql, Object[] obj) throws Exception;
  3. public int findRowCount(String ds, String sql);
  4. }

GenericDaoImpl 实现:

[java] view plaincopy

  1. public class GenericDaoImpl implements GenericDao{
  2. private  JdbcTemplate jdbcTemplateA;
  3. private  JdbcTemplate jdbcTemplateB;
  4. public void setJdbcTemplateA(JdbcTemplate jdbcTemplate) {
  5. this.jdbcTemplateA = jdbcTemplate;
  6. }
  7. public void setJdbcTemplateB(JdbcTemplate jdbcTemplate) {
  8. this.jdbcTemplateB = jdbcTemplate;
  9. }
  10. public int save(String ds, String sql, Object[] obj) throws Exception{
  11. if(null == ds || "".equals(ds)) return -1;
  12. try{
  13. if(ds.equals("A")){
  14. return this.jdbcTemplateA.update(sql, obj);
  15. }else{
  16. return this.jdbcTemplateB.update(sql, obj);
  17. }
  18. }catch(Exception e){
  19. e.printStackTrace();
  20. throw new Exception("执行" + ds + "数据库时失败!");
  21. }
  22. }
  23. public int findRowCount(String ds, String sql) {
  24. if(null == ds || "".equals(ds)) return -1;
  25. if(ds.equals("A")){
  26. return this.jdbcTemplateA.queryForInt(sql);
  27. }else{
  28. return this.jdbcTemplateB.queryForInt(sql);
  29. }
  30. }
  31. }

(2) Service及实现

UserService 接口:

[java] view plaincopy

  1. public interface UserService {
  2. public void saveUser() throws Exception;
  3. }

UserServiceImpl 实现:

[java] view plaincopy

  1. public class UserServiceImpl implements UserService{
  2. private GenericDao genericDao;
  3. public void setGenericDao(GenericDao genericDao) {
  4. this.genericDao = genericDao;
  5. }
  6. public void saveUser() throws Exception {
  7. String userName = "user_" + Math.round(Math.random()*10000);
  8. System.out.println(userName);
  9. StringBuilder sql = new StringBuilder();
  10. sql.append(" insert into t_user(username, gender) values(?,?); ");
  11. Object[] objs = new Object[]{userName,"1"};
  12. genericDao.save("A", sql.toString(), objs);
  13. sql.delete(0, sql.length());
  14. sql.append(" insert into t_user(name, sex) values(?,?); ");
  15. objs = new Object[]{userName,"男的"};//值超出范围
  16. genericDao.save("B", sql.toString(), objs);
  17. }
  18. }

(3) applicationContext-jotm.xml

[java] view plaincopy

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:tx="http://www.springframework.org/schema/tx"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
  9. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11. <description>springJTA</description>
  12. <!--指定Spring配置中用到的属性文件-->
  13. <bean id="propertyConfig"
  14. class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  15. <property name="locations">
  16. <list>
  17. <value>classpath:jdbc.properties</value>
  18. </list>
  19. </property>
  20. </bean>
  21. <!-- JOTM实例 -->
  22. <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean">
  23. <property name="defaultTimeout" value="500000"/>
  24. </bean>
  25. <!-- JTA事务管理器 -->
  26. <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
  27. <property name="userTransaction" ref="jotm" />
  28. </bean>
  29. <!-- 数据源A -->
  30. <bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
  31. <property name="dataSource">
  32. <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
  33. <property name="transactionManager" ref="jotm"/>
  34. <property name="driverName" value="${jdbc.driver}"/>
  35. <property name="url" value="${jdbc.url}"/>
  36. </bean>
  37. </property>
  38. <property name="user" value="${jdbc.username}"/>
  39. <property name="password" value="${jdbc.password}"/>
  40. </bean>
  41. <!-- 数据源B -->
  42. <bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
  43. <property name="dataSource">
  44. <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
  45. <property name="transactionManager" ref="jotm"/>
  46. <property name="driverName" value="${jdbc2.driver}"/>
  47. <property name="url" value="${jdbc2.url}"/>
  48. </bean>
  49. </property>
  50. <property name="user" value="${jdbc2.username}"/>
  51. <property name="password" value="${jdbc2.password}"/>
  52. </bean>
  53. <bean id = "jdbcTemplateA"
  54. class = "org.springframework.jdbc.core.JdbcTemplate">
  55. <property name = "dataSource" ref="dataSourceA"/>
  56. </bean>
  57. <bean id = "jdbcTemplateB"
  58. class = "org.springframework.jdbc.core.JdbcTemplate">
  59. <property name = "dataSource" ref="dataSourceB"/>
  60. </bean>
  61. <!-- 事务切面配置 -->
  62. <aop:config>
  63. <aop:pointcut id="pointCut"
  64. expression="execution(* com.logcd.service..*.*(..))"/><!-- 包及其子包下的所有方法 -->
  65. <aop:advisor pointcut-ref="pointCut" advice-ref="txAdvice"/>
  66. <aop:advisor pointcut="execution(* *..common.service..*.*(..))" advice-ref="txAdvice"/>
  67. </aop:config>
  68. <!-- 通知配置 -->
  69. <tx:advice id="txAdvice" transaction-manager="jtaTransactionManager">
  70. <tx:attributes>
  71. <tx:method name="delete*" rollback-for="Exception"/>
  72. <tx:method name="save*" rollback-for="Exception"/>
  73. <tx:method name="update*" rollback-for="Exception"/>
  74. <tx:method name="find*" read-only="true" rollback-for="Exception"/>
  75. </tx:attributes>
  76. </tx:advice>
  77. <bean id="genericDao"  class="com.logcd.dao.impl.GenericDaoImpl" autowire="byName"> </bean>
  78. <bean id="userService"  class="com.logcd.service.impl.UserServiceImpl" autowire="byName"> </bean>
  79. </beans>

(4) 测试

[java] view plaincopy

  1. public class TestUserService{
  2. private static UserService userService;
  3. @BeforeClass
  4. public static void init(){
  5. ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-jotm.xml");
  6. userService = (UserService)app.getBean("userService");
  7. }
  8. @Test
  9. public void save(){
  10. System.out.println("begin...");
  11. try{
  12. userService.saveUser();
  13. }catch(Exception e){
  14. System.out.println(e.getMessage());
  15. }
  16. System.out.println("finish...");
  17. }
  18. }

二、关于使用atomikos实现 
(1) 数据源配置

[java] view plaincopy

  1. <bean id="dataSourceA" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close">
  2. <property name="uniqueResourceName">
  3. <value>${datasource.uniqueResourceName}</value>
  4. </property>
  5. <property name="xaDataSourceClassName">
  6. <value>${database.driver_class}</value>
  7. </property>
  8. <property name="xaDataSourceProperties">
  9. <value>URL=${database.url};user=${database.username};password=${database.password}</value>
  10. </property>
  11. <property name="exclusiveConnectionMode">
  12. <value>${connection.exclusive.mode}</value>
  13. </property>
  14. <property name="connectionPoolSize">
  15. <value>${connection.pool.size}</value>
  16. </property>
  17. <property name="connectionTimeout">
  18. <value>${connection.timeout}</value>
  19. </property>
  20. <property name="validatingQuery">
  21. <value>SELECT 1</value>
  22. </property>
  23. </bean>

(2)、事务配置

[java] view plaincopy

  1. <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
  2. init-method="init" destroy-method="close">
  3. <property name="forceShutdown" value="true"/>
  4. </bean>
  5. <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
  6. <property name="transactionTimeout" value="${transaction.timeout}"/>
  7. </bean>
  8. <!-- JTA事务管理器 -->
  9. <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
  10. <property name="transactionManager" ref="atomikosTransactionManager"/>
  11. <property name="userTransaction" ref="atomikosUserTransaction"/>
  12. </bean>
  13. <!-- 事务切面配置 -->
  14. <aop:config>
  15. <aop:pointcut id="serviceOperation"  expression="execution(* *..service*..*(..))"/>
  16. <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>
  17. </aop:config>
  18. <!-- 通知配置 -->
  19. <tx:advice id="txAdvice" transaction-manager="springTransactionManager">
  20. <tx:attributes>
  21. <tx:method name="*" rollback-for="Exception"/>
  22. </tx:attributes>
  23. </tx:advice>

有关JTA
JTA全称为Java Transaction API,顾名思义JTA定义了一组统一的事务编程的接口,这些接口如下:
 
XAResource 
XAResource接口是对实现了X/Open CAE规范的资源管理器 (Resource Manager,数据库就是典型的资源管理器) 的抽象,它由资源适配器 (Resource Apdater) 提供实现。XAResource是支持事务控制的核心。

Transaction
Transaction接口是一个事务实例的抽象,通过它可以控制事务内多个资源的提交或者回滚。二阶段提交过程也是由Transaction接口的实现者来完成的。

TransactionManager
托管模式 (managed mode) 下,TransactionManager接口是被应用服务器调用,以控制事务的边界的。
 
UserTransaction
非托管模式 (non-managed mode) 下,应用程序可以通过UserTransaction接口控制事务的边界
 
托管模式下的事务提交场景

注意:在上图中3和5的步骤之间省略了应用程序对资源的操作 (如CRUD)。另外,应用服务器什么时机 enlistResource,又是什么时候delistResource呢?这在后文中会解释。

有关JCA

下图为JCA的架构图

中间涉及元素说明如下:
1)Enterprise Information System
简称EIS,在JTA中它又被称为资源管理器。典型的EIS有数据库,事务处理系统(Transaction Processing System),ERP系统。
 
2)Resource Adapter
资源适配器(Resource Adaper)是JCA的关键。要想把不同的EIS整合(或者连接)到J2EE运行环境中,就必须为每个EIS提供资源适配器,它会将将EIS适配为一个具备统一编程接口的资源 (Resource) 。这个统一编程接口就是上图中的System Contracts和Client API。下面的UML类图将完美诠释资源适配器。

3)Application Server
应用服务器 (Application Server) 通过System Contracts来管理对EIS的安全、事务、连接等。典型的应用服务器有JBoss、JOnAS、Geronimo、GlassFish等。
 
4)Application Component 
应用组件 (Application Component) ,它封装了应用业务逻辑,像对资源的访问和修改。典型的应用组件就是EJB。
 
更多细节请参见:
Sun Microsystems Inc.J2EE Connector Architecture 1.5

参考推荐:

Spring分布式事务实现

JTA与JCA分布式事务

理解 JCA 事务(IBM)

Jencks实现Hibernate与Jackrabbit的分布式事务

时间: 2024-11-09 02:54:27

关于分布式事物 转的相关文章

分布式事物

1.分布式事物简单处理方式一 不出现错误,都提交:出现错误,都回滚: 分布式事物,布布扣,bubuko.com

分布式事物的原理图

分布式事物两阶段提交原理图. blog宗旨:用图说话.

Spring+Mybatis+SpringMVC+Atomikos多数据源共存+分布式事物处理

网上找了一大堆的例子,没一个跑通的,都是copy转发,哎,整理得好辛苦..做个笔记,方便正遇到此问题的猿们能够得到帮助....废话不多说,贴代码..... 项目结构说明: 1.dao层的admin.website包中包含的Mapper.xml文件分别操作不同的数据库 2.举例:192.168.1.1下有个mysql数据库叫 odao_admin 192.168.1.2下有个sqlserver数据库叫 odao_mobile 详情见下方的jdbc.properties文件 1:Pom.xml <p

MySQL分布式事物(XA事物)的使用

有时一个系统的数据 放在不同的库之中.如果用普通的事物 一个分支库提交成功了,另外一个分支库提交失败了, 这候 两个库没有同步的成功或者失败.会导致系统数据的不完整. 对于处理这种情况 MySQL有了处理分布式(XA)事物的语法 XA START xid 用于启动一个带给定xid的XA事物. xid包含3个部分 gtrid,bqual,formatID gtrid 是一个分布式事物的标识符,一个分布式事物的每个XA事物的gtrid必须相同,这样可以明确知道每个XA事物属于哪个分布式事物. bqu

Spring 分布式事物详解

在学习分布式事物的过程中会遇到以下关键名词: 相关名词: XA :XA规范的目的是允许多个资源(如数据库,应用服务器,消息队列,等等)在同一事务中访问,这样可以使ACID属性跨越应用程序而保持有效.XA使用两阶段提交来保证所有资源同时提交或回滚任何特定的事务. JTA: Java事务API(Java Transaction API,简称JTA ) 是一个Java企业版 的应用程序接口,在Java环境中,允许完成跨越多个XA资源的分布式事务. 分布式事物要解决的问题: 把不同支援放到一个事物中,实

mq解决分布式事物问题

今天只看看原理,下一节看项目怎么集成mq进行解决分布式事物. 1.什么情况下会使用到分布式事物? 举例说明:现有一个支付系统,因为项目使用的是微服务框架,有订单模块和支付模块两个模块.生产者进行订单的下单操作购买100元,这时候订单表数据应该是新增一条,然后支付模块的个人账户资金应该是加100元.同一个方法中既需要对订单数据库进行新增又需要调用支付模块对数据进行修改(不同项目不同数据库),这时候就会用到分布式事物,只是举个典型的例子. 那么问题来了,生产者进行订单的下单操作怎么保证订单和支付的数

分布式事物解决方案-TCC

分布式框架下,如何保证事物一致性一直是一个热门话题.当然事物一致性解决方案有很多种(请参考:分布式事物一致性设计思路),我们今天主要介绍TCC方案解决的思路.以下是参与设计讨论的一种解决思路,大家有问题请留言. 1.基本概念 TI:Transaction Interceptor,事务拦截器,位于dapeng容器的filterChain链中. 由于TI的逻辑会比较复杂, 不太适合在IO线程中操作 TM:Transaction Manager, 事务管理器,作为一个独立的服务存在. 事务发起方: 服

Atomikos实现分布式事物管理

分布式事务管理,简单来说就是多个数据库之间的事务管理.之前也试过使用Spring动态切换数据库,通过继承AbstractRoutingDataSource重写determineCurrentLookupKey()方法,来决定使用那个数据库.在开启事务之前,通过改变lookupKey来达到切换数据源目的.但是这种方法多个数据库之前没办法做事务管理,或许对于主从(读写)数据库会好用一些,而对于需要一个操作中更新多个数据库的情况,使用Atomikos或许会更好一些. 本文采用spring4+hiber

分布式事物嵌套事物

1.内部事物 需 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))  否则会出现“已终止事物” 的错误 TransactionScope 分布式事务的使用案例 以及简单说明 TransactionScope 是的.net Framework2.0版本中增加的一个新命名空间.他的用途是为数据库访问提供一个“轻量级”的事物.使用之前必须添加对 System.Transac

ora-01591:锁被未分布式事物处理/Distrib tran

伴随报错内容:         Distrib tran xxx.xxx.xx.x.xxxx          1.使用Oracle DBA用户,查询如下数据字典:select * from dba_2pc_pending 2.强制Rollback或者Commit该事务: select 'commit force '''|| local_tran_id||''';' from dba_2pc_pending; select 'rollback force '''|| local_tran_id|