Showing
1 changed file
with
88 additions
and
0 deletions
技术分享/com.yoho.core.dal.datasource动态数据源切换.md
0 → 100644
1 | +com.yoho.core.dal.datasource多数据源集群动态切换实现逻辑 | ||
2 | +----- | ||
3 | +## 一、大致思路 | ||
4 | +通过配置文件获取多数据源集群信息以及dao接口与数据源的对应关系并保存到MultiDataSourceRouter中,定义类DynamicDataSource继承AbstractRoutingDataSource,实现determineCurrentLookupKey抽象方法(为获取链接的时候提供数据源key),初始化每个dataSource,保存到DynamicDataSource.targetDataSources中,并设置默认的defaultTargetDataSource,生成并注入sqlsessionFactory(dataSource=dynamicDataSource)。 | ||
5 | +定义拦截器在运行时调用dao方法时,通过Dao的信息获取dataSource的key,并设置到MultiDataSourceRouter.dataSourceKey中,在Dao方法具体执行时,会调用determineCurrentLookupKey方法获取刚刚设置的key,从而取得数据源执行数据库操作。 | ||
6 | +在配置文件中通过AOP标签配置该拦截器,设置哪些包会被监控拦截。 | ||
7 | +## 二、具体过程 | ||
8 | +### 1.配置数据源信息 | ||
9 | +使用Yaml格式配置具体如下(order模块示例): | ||
10 | +datasources: | ||
11 | + yh_orders: | ||
12 | + servers: | ||
13 | + - 192.168.102.219:3306 | ||
14 | + - 192.168.102.219:3306 | ||
15 | + username: yh_test | ||
16 | + password: 9nm0icOwt6bMHjMusIfMLw== | ||
17 | + | ||
18 | + yhb_operations: | ||
19 | + servers: | ||
20 | + - 192.168.102.219:3306 | ||
21 | + - 192.168.102.219:3306 | ||
22 | + username: yh_test | ||
23 | + password: 9nm0icOwt6bMHjMusIfMLw== | ||
24 | + daos: | ||
25 | + - com.yoho.yhorder.dal.IGateDAO | ||
26 | +### 2.读取保存数据源信息 | ||
27 | +在spring-mybatis-datasource.xml中配置如下信息进行配置文件的读取并保存到databasesMap中: | ||
28 | + <bean id="databasesMap" class="org.springframework.beans.factory.config.YamlMapFactoryBean"> | ||
29 | + <property name="resources"> | ||
30 | + <list> | ||
31 | + <value>classpath:databases.yml</value> | ||
32 | + </list> | ||
33 | + </property> | ||
34 | + </bean> | ||
35 | +### 3.数据源初始化及相关信息的保存 | ||
36 | +在spring-mybatis-datasource.xml中配置如下信息: | ||
37 | + <bean id="dataSourceBeanFactory" class="com.yoho.core.dal.datasource.DataSourceBeanFactory" init-method="init" > | ||
38 | + <property name="defaultDBUser" value="${db.default.user:yh_vpc_bak}"/> | ||
39 | + <property name="defaultDBPassword" value="${db.default.password:+BfhVxZQ4LuPKt+QxSy9naMwEu/zaKV31I9S8xDJIUA=}"/> | ||
40 | + <property name="databasesMap" ref="databasesMap"/> | ||
41 | + </bean> | ||
42 | +com.yoho.core.dal.datasource.DataSourceBeanFactory的init方法进行初始化具体过程如下: | ||
43 | +#### 3.1解析配置信息 | ||
44 | +从databasesMap中取出key=datasources的数据源信息,遍历处理后生成的信息有: | ||
45 | +dataSource: | ||
46 | +配置文件中的servers下的每个ip都会生成一个dataSource,连接池配置等信息在代码中写死,其他设置信息为beanId=schema@host, | ||
47 | +如上述配置文件中第一schema=yh_orders,该schema有两个dataSource,beanId分别为yh_orders@192.168.102.219:3306,yh_orders@192.168.102.219:3306,每个schema是一个集群保存中Map<String, String> dbClusterSet中。 | ||
48 | +Map<String, String> dbClusterSet:key=schema,value=beanId,beanId,beanId... | ||
49 | +Map<String, String> daoDbClusterMap:key=具体dao,value=schema | ||
50 | +DefaultDBCluster:默认集群,没有指定schema的Dao默认是第一个schema,上述配置文件中是yh_orders。 | ||
51 | +dbClusterSet、daoDbClusterMap、DefaultDBCluster信息保存到MultiDataSourceRouter动态路由对象中。 | ||
52 | +各个dataSource对象实例保存到List<DataSource> dataSources中。 | ||
53 | +#### 3.2生成并注入动态数据源 | ||
54 | +3.2.1定义com.yoho.core.dal.datasource.DynamicDataSource继承AbstractRoutingDataSource实现determineCurrentLookupKey抽象方法, | ||
55 | + @Override | ||
56 | + protected Object determineCurrentLookupKey() { | ||
57 | + return MultiDataSourceRouter.getCurrentDataSourceKey(); | ||
58 | + } | ||
59 | +拦截器在调用dao的方法前会利用DAO的信息通过MultiDataSourceRouter获取到DataSourceKey并设置在MultiDataSourceRouter中,当拦截器invorkDao的方法时会回调determineCurrentLookupKey方法从而路由到正确的DataSource。 | ||
60 | +3.2.2生成并注入DynamicDataSource | ||
61 | +设置beanid=dynamicDataSource, | ||
62 | +初始化每个dataSource放入targetDataSources中, | ||
63 | +targetDataSources=targetDataSources | ||
64 | +3.2.3生成并注入sqlsessionFactory | ||
65 | +实现如下配置: | ||
66 | + <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> | ||
67 | + <property name="dataSource" ref="dynamicDataSource"/> | ||
68 | + <property name="mapperLocations" value="classpath*:META-INF/mybatis/*.xml"></property> | ||
69 | + </bean> | ||
70 | +#### 3.3设置ReadOnlyInSlave | ||
71 | + | ||
72 | +### 4.定义拦截器实现运行时动态路由 | ||
73 | +配置信息如下: | ||
74 | + <!--数据库访问拦截器, 数据库访问延时统计--> | ||
75 | + <bean id="dataSourceMethodInterceptor" class="com.yoho.core.dal.datasource.intercepor.DaoInterceptor"> | ||
76 | + </bean> | ||
77 | + | ||
78 | + <aop:config> | ||
79 | + <aop:pointcut id="daoPoint" | ||
80 | + expression="execution(* com.yoho.*.dal.*.*(..)) or execution(* com.yohobuy.platform.dal.*.*.*(..)) "/> | ||
81 | + <aop:advisor pointcut-ref="daoPoint" advice-ref="dataSourceMethodInterceptor"/> | ||
82 | + </aop:config> | ||
83 | +DaoInterceptor拦截器获取到DAO的类名和statementID,然后执行如下 | ||
84 | +//数据源路由 | ||
85 | + String dataSource = MultiDataSourceRouter.router(mapperNamespace, statementId); | ||
86 | + MultiDataSourceRouter.setDataSourceKey(dataSource); | ||
87 | +在具体数据库操作时(invocation.proceed())会回调DynamicDataSource的determineCurrentLookupKey方法从而路由到正确的DataSource。 | ||
88 | + |
-
Please register or login to post a comment