前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式事务处理

分布式事务处理

作者头像
秋日芒草
发布2018-05-15 17:38:08
9020
发布2018-05-15 17:38:08
举报
文章被收录于专栏:JavaWebJavaWeb

分布式事务处理

        在之前的文章"如何合理的使用动态数据源"中,其实也提到了分布式事务相关的场景如:利用多数据源实现读写分离,但直接使用动态数据源频繁其实是很消耗资源的,而且就是当业务service一个方法中的业务涉及到多数据源来回操作的时候会存在没法保证事务的ACID,基于多数据源这个事务问题,找到了一个比较好的解决方案,能进行分布式的处理,还能保住事务的ACID,首先我们先了解一下什么事务?事务的四大特性分别都是什么意思?

事务:是一组SQL组成的"逻辑处理单元"。

原子性(Atomicity):原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。

一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(Durability):持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

1.     那什么是分布式事务?

其实简单的理解就是为了保证"不同数据库的数据的一致性"。

2.     分布式事务产生的场景"数据库的分库分表"和"SOA服务化"。

3.     那要想做到做的分布式事务,我们应当怎么做了,最好的办法我们先去了解什么是XA协议。

个人对上面文字理解如下(不一定对,只是个人的理解):

正确理解如下:

3.     XA模式的优缺点:

优点:简单,使用分布式成本低。

缺点:性能不理想,XA无法满足高并发的场景,许多Nosql是不支持XA协议的。

4.     其实除了XA这种解决分布式事务的方法外,还有如下的解决方案,其他的解决方案等有时间再整理。

解决方案:XA,可靠性消息模式,TCC,补偿模式

5.     重点来了,就是Atomikos了,Atomikos是一个为Java平台提供的开源事务管理器。

主要功能:全面奔溃/重启恢复,嵌套事务,为XA和非XA提供内置的JDBC适配器,是标准SUM公司的JTA API的实现。

6.     既然都已经介绍了Atomikos强大功能了,那我们一起搭建一个基于SSM框架的测试代码,测试这个Atomikos的功能是不是都是吹的,核心配置如下:

pom.xml 配置如下:

代码语言:javascript
复制
<!-- 第一步:实现了XA协议的开源第三方支持包  -->
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>atomikos-util</artifactId>
	<version>3.7.0</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-jta</artifactId>
	<version>3.7.0</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-api</artifactId>
	<version>3.7.0</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-jdbc</artifactId>
	<version>3.7.0</version>
</dependency>
<dependency>
	<groupId>org.codehaus.btm</groupId>
	<artifactId>btm</artifactId>
	<version>2.1.4</version>
</dependency>
<!-- 第一步:实现了XA协议的开源第三方支持包  -->

config.properties 配置如下:

代码语言:javascript
复制
# =====================本地环境=====================
his.db.url=jdbc:mysql://localhost:3306/his?useUnicode=true&amp;characterEncoding=UTF-8
his.db.user=root
his.db.password=root

hispay.db.url=jdbc:mysql://localhost:3306/his_pay?useUnicode=true&amp;characterEncoding=UTF-8
hispay.db.user=root
hispay.db.password=root
# =====================本地环境=====================

jta.properties 配置如下:

代码语言:javascript
复制
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.console_file_name = tm.out
com.atomikos.icatch.log_base_name = tmlog
com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm
com.atomikos.icatch.console_log_level = INFO
# out log
com.atomikos.icatch.output_dir=/hello/atomikos
com.atomikos.icatch.log_base_dir=/hello/atomikos
com.atomikos.icatch.serial_jta_transactions=false

spring-dispatcher.xml 核心配置如下:

代码语言:javascript
复制
<context:property-placeholder location="classpath:config.properties" />
<bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init"
	  destroy-method="close" abstract="true">
	<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
	<property name="poolSize" value="10" />
	<property name="minPoolSize" value="10"/>
	<property name="maxPoolSize" value="30"/>
	<property name="borrowConnectionTimeout" value="60"/>
	<property name="reapTimeout" value="20"/>
	<!-- 最大空闲时间 -->
	<property name="maxIdleTime" value="60"/>
	<property name="maintenanceInterval" value="60"/>
	<property name="loginTimeout" value="60"/>
	<property name="testQuery">
		<value>select 1</value>
	</property>
</bean>

<!-- his数据源  -->
<bean id="hisDataSource" parent="abstractXADataSource">
	<!-- value只要两个数据源不同就行,随便取名 -->
	<property name="uniqueResourceName" value="mysql/his" />
	<property name="xaDataSourceClassName"
			  value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
	<property name="xaProperties">
		<props>
			<prop key="URL">${his.db.url}</prop>
			<prop key="user">${his.db.user}</prop>
			<prop key="password">${his.db.password}</prop>
			<prop key="pinGlobalTxToPhysicalConnection">true</prop>
		</props>
	</property>
</bean>

<bean id="hispayDataSource" parent="abstractXADataSource">
	<!-- value只要两个数据源不同就行,随便取名 -->
	<property name="uniqueResourceName" value="mysql/hispay" />
	<property name="xaDataSourceClassName"
			  value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
	<property name="xaProperties">
		<props>
			<prop key="URL">${hispay.db.url}</prop>
			<prop key="user">${hispay.db.user}</prop>
			<prop key="password">${hispay.db.password}</prop>
			<prop key="pinGlobalTxToPhysicalConnection">true</prop>
		</props>
	</property>
</bean>


<bean id="hisSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="hisDataSource" />
	<property name="mapperLocations" value="classpath:mybatis/xml/his/*Mapper.xml" />
</bean>

<bean id="hispaySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="hispayDataSource" />
	<property name="mapperLocations" value="classpath:mybatis/xml/hispay/*Mapper.xml" />
</bean>

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
	  init-method="init" destroy-method="close">
	<!-- atomikosTransactionManager 这个事务管理器可以关闭事务true  --> 
	<property name="forceShutdown">
		<value>true</value>
	</property>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
	<property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager"
	  class="org.springframework.transaction.jta.JtaTransactionManager">
	<property name="transactionManager">
		<ref bean="atomikosTransactionManager"/>
	</property>
	<property name="userTransaction">
		<ref bean="atomikosUserTransaction"/>
	</property>
	<!-- 必须设置,否则程序出现异常 JtaTransactionManager does not support custom isolation levels by default -->
	<property name="allowCustomIsolationLevels" value="true"/>

</bean>


 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="cn.edu.his.pay.mapper.his"/>
	<property name="sqlSessionFactoryBeanName" value="hisSqlSessionFactory" />
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="cn.edu.his.pay.mapper.hispay"/>
	<property name="sqlSessionFactoryBeanName" value="hispaySqlSessionFactory" />
</bean>

<!-- 一定要开启注解事务支持  -->
<tx:annotation-driven transaction-manager="transactionManager"/>

总结:到这里Atomikos集成到SSM框架就算完成了,这篇文章就不进行详细的,对于Atomikos(分布式事务管理框架)的特性,我会在下篇文章中写测试代码去分别测试Atomikos的强大功能。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分布式事务处理
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档