文档章节

数据库集群模式多库分表情况下事务的管理的初步方案

漂泊者及其影子
 漂泊者及其影子
发布于 2016/03/30 17:43
字数 1188
阅读 434
收藏 11

一、场景描述

假设一个项目需要十个数据源,通过spring aop 我们要如何管理事务,单个数据源的时候我们使用一个切面来进行管理,十个数据源是否表示需要十个切面,每个切面是否需要开启十个事务然后再关闭十个事务。


二、单数据源的事务管理


<!-- 自动代理 -->
	<bean id="autoproxy"
		class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<!-- 可以是Service或DAO层(最好是针对业务层*Service) -->
		<property name="beanNames">
			<list>
				<value>*Service</value>
				<value>*ServiceImpl</value>
			</list>
		</property>
		<property name="interceptorNames">
			<!-- 一个transactionIterceptor表示一个切面,进行一次拦截 -->
			<list>
				<value>transactionInterceptor</value>
			</list>
		</property>
	</bean>


三、多数据源事务管理初步方案

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<!-- data source settings -->
	<!-- <bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
		<property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> 
		<property name="url"> <value>jdbc:mysql://192.168.5.175:3306/zcode_shard1?characterEncoding=utf-8&amp;autoReconnect=true 
		</value> </property> <property name="username"> <value>root</value> </property> 
		<property name="password"> <value>123456</value> </property> </bean> -->

	<!-- datasource settings begin -->
	<bean id="dataSource0"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard0?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource1"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard1?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource2"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard2?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource3"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard3?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource4"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard4?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource5"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard5?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource6"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard6?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource7"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard7?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource8"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard8?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="dataSource9"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.5.175:3306/zcode_shard9?characterEncoding=utf-8&amp;autoReconnect=true
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>

	<bean id="dynamicDataSource" class="com.iflashbuy.base.DynamicDataSource">
		<property name="targetDataSources">
			<map key-type="java.lang.String">
				<entry value-ref="dataSource0" key="dataSource0"></entry>
				<entry value-ref="dataSource1" key="dataSource1"></entry>
			</map>
		</property>
		<!-- 视情况而定看是否需要设置默认数据源 -->
		<property name="defaultTargetDataSource" ref="dataSource0">
		</property>
	</bean>



	<!-- datasource settings end -->

	<!-- jdbctemplate config begin -->

	<bean id="shardJdbcTemplate"
		class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
		<constructor-arg ref="dynamicDataSource" />
	</bean>


	<!-- jdbctemplate config end -->


	<!-- transactionManager config begin -->

	<bean id="shardTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dynamicDataSource" />
	</bean>

	<!-- transactionManager config end -->





	<!-- transactionInterceptor config begin -->

	<bean id="shardTransactionInterceptor"
		class="org.springframework.transaction.interceptor.TransactionInterceptor">
		<property name="transactionManager">
			<ref bean="shardTransactionManager" />
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="load*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="query*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="is*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="has*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="exist*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="check*">PROPAGATION_SUPPORTS,readOnly</prop>
				<prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
			</props>
		</property>

	</bean>

	<!-- transactionInterceptor config end -->
	<!-- 自动代理 -->
	<bean id="autoproxy"
		class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<!-- 可以是Service或DAO层(最好是针对业务层*Service) -->
		<property name="beanNames">
			<list>
				<value>*Service</value>
				<value>*ServiceImpl</value>
			</list>
		</property>
		<property name="interceptorNames">
			<!-- 自动代理开启两个拦截器 -->
			<list>
				<value>shardTransactionInterceptor</value>
			</list>
		</property>
	</bean>
</beans>



大致方案通过重写spring拦截器对数据源进行动态切换,这样便可以做到每个请求只做一次拦截,每个拦截只开启一个事务.



四、多事务模式下编码注意事项

假设是多数据数据批量操作需要预先对数据进行分组,同一数据源的数据尽量一起操作,以避免事务不断打开又关闭,降低效率也提高了数据库服务器的压力。


© 著作权归作者所有

漂泊者及其影子
粉丝 43
博文 121
码字总数 72105
作品 0
广州
程序员
私信 提问
浙江移动首个基于阿里云技术的生产应用上线成功

一、项目背景 为落实公司“十三五”战略,建立“架构先进、运营高效、内外兼顾”的IT体系, 浙江移动近日受总部信息技术中心委托和指导,探索传统企业与互联网公司新型合作模式,跟踪行业发展...

阿里云头条
2018/05/11
0
0
追求极致的数据库分区分表方案

序言 一直在做企业应用,目前要做一些互联网应用,当然只是应用是放在互联网的,数据量距离真正的互联网应用还是有相当大的差距的。但是不可避免的,在数据库出现瓶颈的情况还是有的,现在做...

悠悠然然
2016/02/19
3.6K
7
【分布式架构之旅-理论篇】数据库分库分表

前言 储备知识ing,很久之前写的。 MySQL集群 MySQL官方提供的是mysql-proxy方案,主要解决了高并发的问题,但是没有解决高可用的问题。一般项目都是读多写少。读的操作让mysql-slave去处理,...

cmazxiaoma
2017/12/18
0
0
分库分表事宜

分库分表概念 按字面解释,分库是把原本存储于一个库的数据分块存储到多个库上,分表是把原本存储于一个表的数据分块存储到多个表上。 合理的分库可以降低单台服务器的负载压力,合理的分表可...

wangshuaixin
2016/12/18
59
0
Jav高级开发订单系统分库分表实践及mycat分表分库的原理你知道吗

Jav高级开发订单系统分库分表实践及mycat分表分库的原理你知道吗 引言 从字面上简单理解,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。 ...

java编程大飞哥
2017/10/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Feign Retryer的默认重试策略测试

1、Feign配置 @Configurationpublic class FeignConfig { @Value("${coupon_service.url:http://localhost:8081}") private String couponServiceUrl; @Bean publ......

moon888
19分钟前
1
0
关于不同域名下的session共享问题

如果登录,首页,分类,列表,产品都在不同的二级域名下,主域名不变,一定要保证里面的版本问题,不能为了更新而更新,这样哪个下面的session都访问不了。

dragon_tech
20分钟前
1
0
iOS 中文拼音互转(好东西记录一下)

PinYin4Objc

_____1____
28分钟前
1
0
fabric private data实战

Hyperledger Fabric private data是1.2版本引入的新特性,fabric private data是利用旁支数据库(SideDB)来保存若干个通道成员之间的私有数据,从而在通道之上又提供了一层更灵活的数据保护...

汇智网教程
28分钟前
1
0
es之聚合查询汇总

记录一下最近用到的es聚合查询,感觉常见的应该多遇上了,下午抽空更新

我真是小菜鸡
29分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部