事務可以分爲三個等級:
1,強一致性
事務中未提交的數據不會被其他事務獲取,但本事務中可以查看未提交數據。
常用的本地事務就屬於強一致性事務。
2,一般一致性
事務中未提交的數據不會被其他事務獲取,但重新獲取的相同事務編號的分佈式事務中也無法查看未提交數據。
兩階段提交時,不同的進程中使用分佈式事務,採用獨立分佈式資源管理器時,屬於一般一致性。
3,最終一致性
通過消息發送或重試方式保證不用進程中最終數據一致。
可以看出,跨系統的兩階段提交不能實現強一致性。
使用micro-datasource可以實現跨系統強一致性。
應用原理:
使用micro-datasource數據源使事務與線程解耦,通過groupid在其他線程進行事務提交或回滾。
多個系統需要統一提交時,通過activemq發送提交消息(含有groupid),各系統收到消息後進行統一提交或回滾。
micro-datasource數據源與Mybatis或hibernate或jdbcTemplate等orm框架可以整合使用
原理是micro-datasource包中提供了路由數據源方案,通過aop動態切換普通數據源和分佈式數據源
使用普通數據源時仍接受傳統事務管理器管理
jar包下載:
需要使用nh-micro-datasource.jar
依賴log4j.jar\org.springframework.beans.jar\org.springframework.aop.jar\org.springframework.core.jar\aopalliance.jar
<dependency> <groupId>com.github.jeffreyning</groupId> <artifactId>nh-micro-datasource</artifactId> <version>1.0.0-RELEASE</version> </dependency>
|
jms通知功能需要使用nh-micro-datasource-msg.jar
依賴geronimo-j2ee-management.jar/geronimo-jms.jar/activemq-core.jar
<dependency> <groupId>com.github.jeffreyning</groupId> <artifactId>nh-micro-datasource-msg</artifactId> <version>1.0.0-RELEASE</version> </dependency>
|
分佈式數據源配置樣例:
<!– micro分佈式數據源 --> <bean id="local_xa_dataSource" class="com.nh.micro.datasource.MicroXaDataSourceFactory" factory-method="createDataSource" init-method=“init”> <!– 多個micro分佈式數據源實例時可設置不同的dataSourceId 默認爲default --> <constructor-arg value=“default”/> <property name="url" value="${database.url}" /> <property name="username" value="${database.user}" /> <property name="password" value="${database.password}" /> <property name="minSize" value=“5" /> <property name="maxSize" value=“20" /> <property name=“dirverClassName” value=“com.mysql.jdbc.Driver” /> <property name=“validationQuery” value=“select 'x' from dual” /> </bean> <!-- micro動態切換數據源配置 --> <bean id="dynamic_xa_dataSource" class="com.nh.micro.datasource.MicroDynamicDataSource" > <property name="targetDataSources"> <map key-type="java.lang.String"> <!– 設置目標數據源爲分佈式事務數據源 --> <entry key="local_xa_dataSource" value-ref="local_xa_dataSource"></entry> </map> </property> <!-- 默認目標數據源爲主庫普通數據源 --> <property name="defaultTargetDataSource" ref="dataSource"/> </bean> <!-- define the Mybatis SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!– Mybatis引入micro動態切換數據源實例 --> <property name="dataSource" ref="dynamic_xa_dataSource"/> <property name="typeAliasesPackage" value="foo.model"/> </bean> <aop:config> <aop:pointcut id="testPointcut" expression="execution( * foo.repository.TestRep.*(..))"/> <aop:advisor pointcut-ref="testPointcut" advice-ref="dataSourceAdvice"/> </aop:config>
|
設置切換分佈式數據源的aop:
<!– 設置service層或dao層aop用來動態切換數據源 --> <bean class="com.nh.micro.datasource.DataSourceAdvice" id="dataSourceAdvice"> <property name="readMethodList"> <list> </list> </property> </bean> <aop:config> <aop:pointcut id="testPointcut" expression="execution( * foo.repository.TestRep.*(..))"/> <aop:advisor pointcut-ref="testPointcut" advice-ref="dataSourceAdvice"/> </aop:config>
|
代碼中通過註解設置哪些方法需切換爲分佈式數據源:
//Mybatis的Dao接口代碼示例,使用@ChangeDataSource註解決定是否切換爲分佈式事務數據源 package foo.repository; import java.util.Map; import com.nh.micro.datasource.ChangeDataSource; public interface TestRep { @ChangeDataSource(name="local_xa_dataSource") public int updateInfo(Map paramMap); @ChangeDataSource(name="local_xa_dataSource") public int insertInfo(Map paramMap); }
|
執行過程樣例:
//設置xaGroupId和xaBranchId MicroXaDataSource.setXid(groupId,branchId); //從Spring中取dao接口對象調用相關業務方法 TestRep testRep=MicroContextHolder.getContext().getBean("testRep"); Map paramMap=new HashMap(); paramMap.put("meta_key", metaKey); paramMap.put("id", id); testRep.insertInfo(paramMap); //可以在其他的線程中根據xaGroupId提交或回滾分佈式事務 MicroXaDataSourceFactory.getDataSourceInstance(“default”).commit(groupid);
|
設置事務提交消息接收和發送對象:
//設置activemq發送對象,發送commit/rollback命令給其他系統 <bean class="com.nh.micro.datasource.msg.MicroDataSourceJmsReceiver" init-method="init"> <property name="jmsUrl" value="tcp://10.10.xx.xx:61616"></property> </bean> //通知其他系統提交的命令是(groupid爲參數) //commit MicroDataSourceJmsSender.sendXaMsg("commit", groupId); //rollback MicroDataSourceJmsSender.sendXaMsg(“rollback", groupId); //設置activemq接收對象,接收從其他系統發來的commit/rollback命令,MicroDataSourceJmsReceiver內部收到消息後會負責根據groupid提交或回滾事務 <bean class="com.nh.micro.datasource.msg.MicroDataSourceJmsSender"> <property name="jmsUrl" value="tcp://10.10.xx.xx:61616"></property> </bean> |