使用nhmicro的micro-datasource嵌入式解决微服务架构分布式事务问题

分布式事务可以分为三个等级:

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>

 










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值