国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Spring + Atomikos 分布式事務(wù)實現(xiàn)方式


             前段時間發(fā)現(xiàn)對分布式事務(wù)了解的不夠清晰,最近又重新看了一下分布式事務(wù),簡單做個記錄,以后方便查看
Java規(guī)范對分布式事務(wù)定義了標(biāo)準(zhǔn)的規(guī)范Java事務(wù)API和Java事務(wù)服務(wù),分別是JTA和JTS
一個分布式事務(wù)必須包括一個事務(wù)管理器和多個資源管理器,
資源管理器是任意類型的持久化數(shù)據(jù)存儲,而事務(wù)管理器則是承擔(dān)著所有事務(wù)參與單元者的相互通訊的責(zé)任
JTA的規(guī)范制定了分布式事務(wù)的實現(xiàn)的整套流程框架,定義了各個接口且只有接口,而實現(xiàn)分別交給事務(wù)管理器的實現(xiàn)方和資源管理器的實現(xiàn)方
對于資源管理器而言,主要包括數(shù)據(jù)庫連接,JMS等,還有很多了解的不清楚
對于事務(wù)管理器而言,從網(wǎng)上了解主要是應(yīng)用服務(wù)器,包括JBOSS,WEBLOGIC等應(yīng)用服務(wù)器,也就是說事務(wù)管理器的實現(xiàn)方是應(yīng)用服務(wù)器,用來管理事務(wù)的通訊和協(xié)調(diào)
對于大多數(shù)談的數(shù)據(jù)庫了解,事務(wù)管理器需要從數(shù)據(jù)庫獲得XAConnection , XAResource等對象,而這些對象是數(shù)據(jù)庫驅(qū)動程序需要提供的
所以如果要實現(xiàn)分布式事務(wù)還必須有支持分布式事務(wù)的數(shù)據(jù)庫服務(wù)器以及數(shù)據(jù)庫驅(qū)動程序


對Mysql而言,在mysql5.0以上的版本已經(jīng)支持了分布式事務(wù),另外常用的mysql-connector-java-5.1.25-bin.jar也是支持分布式事務(wù)的
可以在jar包的com.mysql.jdbc.jdbc2.optional中找到XA對象的實現(xiàn)
上面介紹了事務(wù)管理器和資源管理器的實現(xiàn)方式,在學(xué)習(xí)研究過程中發(fā)現(xiàn)對于事務(wù)管理器,特別強調(diào)了tomcat等服務(wù)器是不支持的,這句話的意思應(yīng)該是在tomcat容器內(nèi)
并沒有分布式事務(wù)管理器的實現(xiàn)對象。而在JBOSS或者WEBLOGIC等商業(yè)服務(wù)器應(yīng)該內(nèi)置了分布式事務(wù)管理器的實現(xiàn)對象,應(yīng)用程序可以通過JNDI方式獲取UserTransaction
和TransactionManager等分布式事務(wù)環(huán)境中所需要用到的對象




事務(wù)管理器作為管理和協(xié)調(diào)分布式事務(wù)的關(guān)鍵處理中心非常重要,所以應(yīng)用服務(wù)器可以單獨只用過事務(wù)管理器。




上圖具體文章鏈接為http://blog.csdn.net/xiaol_zhong/article/details/7983863




上面主要是一些基本的概念,在學(xué)習(xí)研究中總結(jié)出來的,可能不太全面,下面主要介紹一下在使用Spring使用分布式事務(wù)中的心得,這種做法也是將事務(wù)管理器嵌入應(yīng)用中。


開始準(zhǔn)備Spring的時候,網(wǎng)上介紹了Jotm以及Atomikos等工具,實際上這些工具都是取代應(yīng)用服務(wù)器對事務(wù)管理器的支持,負責(zé)實現(xiàn)事務(wù)管理器對象


Jotm需要使用特定數(shù)據(jù)庫連接池enhydra,而且網(wǎng)上說因為維護時間久遠,問題不少,所以直接使用Atomikos進行測試


在Maven上下載了Atomikos的3.9.0版本的相關(guān)需要jar包。主要包括


atomikos-util-3.9.0.jar   transactions-3.9.0.jar  transactions-api-3.9.0.jar  transactions-jdbc-3.9.0.jar  transactions-jta-3.9.0.jar  jta-1.1.jar 


下面看一下主要的配置文件的配置方式:
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3.   
  4. <beans xmlns="http://www.springframework.org/schema/beans"  
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
  6. xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"  
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  8.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
  9.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
  10.            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
  11. <bean id="dataSource0" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
  12. <property name="driverClass" value="com.mysql.jdbc.Driver" />  
  13. <property name="jdbcUrl" value="jdbc:mysql://172.17.2.5:3003/jta" />  
  14. <property name="user" value="root" />  
  15. <property name="password" value="ems" />  
  16. <property name="autoCommitOnClose" value="true" />  
  17. </bean>  
  18.    
  19. <bean id="dataSource1" class="com.atomikos.jdbc.AtomikosDataSourceBean"  
  20. init-method="init" destroy-method="close">  
  21. <property name="uniqueResourceName" value="ds1" />  
  22. <property name="xaDataSourceClassName"  
  23. value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />  
  24. <property name="xaProperties">  
  25. <props>  
  26. <prop key="url">jdbc:mysql://172.17.2.5:3003/jta</prop>  
  27. <prop key="user">root</prop>  
  28. <prop key="password">ems</prop>  
  29. </props>  
  30. </property>  
  31. <property name="minPoolSize" value="10" />  
  32. <property name="maxPoolSize" value="100" />  
  33. <property name="borrowConnectionTimeout" value="30" />  
  34. <property name="testQuery" value="select 1" />  
  35. <property name="maintenanceInterval" value="60" />  
  36. </bean>  
  37.   
  38.   
  39. <bean id="dataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean"  
  40. init-method="init" destroy-method="close">  
  41. <property name="uniqueResourceName" value="ds2" />  
  42. <property name="xaDataSourceClassName"  
  43. value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />  
  44. <property name="xaProperties">  
  45. <props>  
  46. <prop key="url">jdbc:mysql://172.17.2.5:3306/jta</prop>  
  47. <prop key="user">root</prop>  
  48. <prop key="password">ems</prop>  
  49. </props>  
  50. </property>  
  51. <property name="minPoolSize" value="10" />  
  52. <property name="maxPoolSize" value="100" />  
  53. <property name="borrowConnectionTimeout" value="30" />  
  54. <property name="testQuery" value="select 1" />  
  55. <property name="maintenanceInterval" value="60" />  
  56. </bean>  
  57.   
  58. <bean id="dataSource3" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
  59. <property name="driverClass" value="com.mysql.jdbc.Driver" />  
  60. <property name="jdbcUrl" value="jdbc:mysql://172.17.2.5:3306/jta" />  
  61. <property name="user" value="root" />  
  62. <property name="password" value="ems" />  
  63. <property name="autoCommitOnClose" value="true" />  
  64. </bean>  
  65.   
  66.   
  67. <!--SqlMap setup for MyBatis Database Layer -->  
  68. <bean id="sqlSessionFactoryForD1" class="org.mybatis.spring.SqlSessionFactoryBean">  
  69. <property name="dataSource" ref="dataSource1" />  
  70. <property name="mapperLocations" value="classpath:jtaatomikos/jta.xml" />  
  71. </bean>  
  72. <bean id="sqlSessionTemplateForD1" class="org.mybatis.spring.SqlSessionTemplate">  
  73. <constructor-arg index="0" ref="sqlSessionFactoryForD1" />  
  74. </bean>  
  75.   
  76.   
  77. <bean id="sqlSessionFactoryForD2" class="org.mybatis.spring.SqlSessionFactoryBean">  
  78. <property name="dataSource" ref="dataSource2" />  
  79. <property name="mapperLocations" value="classpath:jtaatomikos/jta.xml" />  
  80. </bean>  
  81. <bean id="sqlSessionTemplateForD2" class="org.mybatis.spring.SqlSessionTemplate">  
  82. <constructor-arg index="0" ref="sqlSessionFactoryForD2" />  
  83. </bean>  
  84.   
  85.   
  86. <!-- Config JTA UserTransactionManager Impl -->  
  87. <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"  
  88. init-method="init" destroy-method="close">  
  89. <property name="forceShutdown">  
  90. <value>true</value>  
  91. </property>  
  92. </bean>  
  93.   
  94.   
  95.   
  96.   
  97. <!-- Config JTA UserTransaction Impl -->  
  98. <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">  
  99. <property name="transactionTimeout">  
  100. <value>300</value>  
  101. </property>  
  102. </bean>  
  103.   
  104.   
  105. <!-- Spring JtaTransactionManager Config -->  
  106. <bean id="springJTATransactionManager"  
  107. class="org.springframework.transaction.jta.JtaTransactionManager">  
  108. <property name="transactionManager">  
  109. <ref bean="atomikosTransactionManager" />  
  110. </property>  
  111. <property name="userTransaction">  
  112. <ref bean="atomikosUserTransaction" />  
  113. </property>  
  114. </bean>  
  115.   
  116. <bean id="transactionManager"  
  117. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  118. <property name="dataSource" ref="dataSource1" />  
  119. </bean>  
  120.   
  121.   
  122.     <!-- Aop Config -->  
  123. <aop:config>  
  124. <aop:pointcut id="jtaServiceOperation"  
  125. expression="execution(* jtaatomikos.*Service.*(..))"></aop:pointcut>  
  126. <aop:advisor pointcut-ref="jtaServiceOperation"  
  127. advice-ref="txAdvice"></aop:advisor>  
  128. </aop:config>  
  129.   
  130.   
  131.     <!-- Transacation Advice Handle -->  
  132. <tx:advice id="txAdvice" transaction-manager="springJTATransactionManager">  
  133. <tx:attributes>  
  134. <tx:method name="update*" rollback-for="Exception" />  
  135. </tx:attributes>  
  136. </tx:advice>  
  137.   
  138.   
  139.   
  140.   
  141. <context:component-scan base-package="jtaatomikos"></context:component-scan>  
  142.   
  143.   
  144.   
  145.   
  146. </beans>  




下面分別對每段配置進行部分記錄
分別定義了dataSource0 dataSource1 dataSource2 dataSource3 
其中0和3都是普通的C3P0數(shù)據(jù)庫連接池,而1和2是AtomikosDataSourceBean
定義0和3的目的是在后面的測試中測試如果不是AtomikosDataSourceBean的連接是不能加入到分布式事務(wù)中的
接著定義了兩個sqlSessionTemplate,分別對應(yīng)3003和3306兩個數(shù)據(jù)庫。對應(yīng)程序中的兩個Dao
下面是定義分布式事務(wù)最重要的兩個實現(xiàn)UserTransactionManager和UserTransactionImpl,均使用Atomikos中的實現(xiàn)
接著是Spring的AOP代理所使用的事務(wù)處理器springJTATransactionManager,這是Spring自帶的JTA實現(xiàn)類,但是Spring只負責(zé)提供接口,真正內(nèi)部實現(xiàn)分布式事務(wù)的上面定義
的兩個對象,所以需要將上面定義的兩個對象進行注入,所以Spring框架負責(zé)提供接口,Atomikos負責(zé)實現(xiàn)
另外再定義一個transactionManager是為了測試在傳統(tǒng)的Spring事務(wù)方式下,為什么不能支持分布式事務(wù)
后面就是為了測試定義的AOP配置,不再多說
再來看看具體測試實現(xiàn),只貼出核心測試方法
存在Service如下
 
  1. public interface D1Service {  
  2.       
  3.     void updateAccount(Integer account);  
  4.   
  5.   
  6. }  




實現(xiàn)如下:

  1. public void updateAccount(Integer account) {  
  2.         int userAId = 1;  
  3.         int userBId = 2;  
  4.         int userA_Account = d1Dao.getAccount(userAId);  
  5.         int userB_Account = d2Dao.getAccount(userBId);  
  6.         d1Dao.saveAccount(userAId, userA_Account + account);  
  7.         d2Dao.saveAccount(userBId, userB_Account - account);  
  8.         if(userB_Account - account < 0){  
  9.             throw new AccountNotEnoughException();  
  10.         }  
  11.     }  


分別在3003和3306數(shù)據(jù)庫上新建相同的數(shù)據(jù)庫表,簡單測試需要字段userId和account,初始化定義數(shù)據(jù)為1 10000 ; 2 10000;
代表用戶1和2分別賬戶有10000。
測試程序如下:

  1. <pre name="code" class="java">public static void main(String[] args) {  
  2.         ApplicationContext appContext = new ClassPathXmlApplicationContext("jtaatomikos/application-jta-atomikos.xml");  
  3.         D1Service service = (D1Service) appContext.getBean("d1Service");  
  4.         service.updateAccount(1000);  
  5.         service.updateAccount(9100);  
  6.     }  


很明顯在執(zhí)行轉(zhuǎn)賬1000的時候,是沒有問題的,在第二部執(zhí)行轉(zhuǎn)賬9100的時候,由于userB_Account-account< 0 成立所以會有異常拋出
此時就是測試分布式事務(wù)的關(guān)鍵
假設(shè)以下幾種情況
在使用springJTATransactionManager的情況下


1  均使用正確的AtomikosDataSourceBean,此時兩個事務(wù)均能正確回滾
2  如果分別使用AtomikosDataSourceBean和C3P0,則只有前者對應(yīng)數(shù)據(jù)庫會回滾,而后者則不會回滾,猜想這是因為 springJTATransactionManager在處理事務(wù)的時候, 內(nèi)部的atomikosTransactionManager只會將AtomokosDataSourceBean加入到分布式事務(wù)中,而不考慮其他連接方式
3  如果均使用C3P0,根據(jù)上面的解釋,很清楚的可以猜到兩個數(shù)據(jù)庫的數(shù)據(jù)均不會回滾,測試結(jié)果也符合該預(yù)期
再來談?wù)劮植际绞聞?wù)為什么需要使用springJTATransactionManager
Spring傳統(tǒng)的事務(wù)管理均使用
org.springframework.jdbc.datasource.DataSourceTransactionManager,那這種事務(wù)管理器為什么不能支持分布式事務(wù)呢?
從配置中可以看出該對象需要注入dataSource屬性,注意只能注入單一的dataSource,顯然這是不符合分布式事務(wù)的必須使用多個數(shù)據(jù)庫這一基礎(chǔ)的,所以在使用傳統(tǒng)的該事務(wù)管理器,只能選擇一個數(shù)據(jù)連接進行事務(wù)管理,本身來說Spring的事務(wù)管理也是基于這點實現(xiàn)的,保證事務(wù)管理內(nèi)的所有數(shù)據(jù)庫操作均使用同一個Connection,例如Connection的begin和commit以及rollback控制事務(wù)。
當(dāng)使用org.springframework.jdbc.datasource.DataSourceTransactionManager 
測試結(jié)果如下:
第一個結(jié)論:無論使用DataSource0 - DataSource3 中的任何一個,均能正?;貪L,也就是說該事務(wù)管理器不依賴DataSource的具體實現(xiàn),不論是Atomikos的實現(xiàn)或者是其他的數(shù)據(jù)庫連接實現(xiàn),均能夠被傳統(tǒng)的事務(wù)管理器管理
第二個結(jié)論:因為該事務(wù)管理器只能配置單一的DataSource,所以只能保證配置的DataSource能被事務(wù)管理,其它的DataSource都不受事務(wù)控制,其原理也很顯而易見,因為傳統(tǒng)的事務(wù)管理器使用單一Connection進行事務(wù)管理,在分布式事務(wù)多個不同數(shù)據(jù)庫的Connection條件下,顯然這種實現(xiàn)方式不能成立。所以需要Atimikos提供實現(xiàn)了JTA規(guī)范標(biāo)準(zhǔn)的事務(wù)管理器


關(guān)于JTA的兩段提交方案,網(wǎng)上也很多教程,后面自己也會進行一步步實踐,后面會跟進進行記錄

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Matrix - 與 Java 共舞 - 不需要應(yīng)用服務(wù)器的J2EE
在spring、tomcat中使用多數(shù)據(jù)源并支持分布式事務(wù)管理
SpringBoot整合分布式事務(wù),JTA+Atomikos實現(xiàn)多數(shù)據(jù)源
分布式事務(wù)(一)兩階段提交及JTA
一個注解搞定分布式事務(wù)
XA transactions using Spring | JavaWorld
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服