當前位置:
首頁 >
MySQL读写分离应用层实现
發布時間:2025/3/20
50
豆豆
生活随笔
收集整理的這篇文章主要介紹了
MySQL读写分离应用层实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
基于Spring的AOP
在應用層,實現讀寫分離
在請求進入Service之前,使用AOP來做出判斷
判斷方式
是使用寫庫還是讀庫,判斷依據可以根據方法名判斷
比如,以query、find、get等開頭的就走讀庫,其他的走寫庫
DynamicDataSource
定義動態數據源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/*** 定義動態數據源,實現通過集成Spring提供的AbstractRoutingDataSource,只需要實現determineCurrentLookupKey方法即可* * 由于DynamicDataSource是單例的,線程不安全的,所以采用ThreadLocal保證線程安全,由DynamicDataSourceHolder完成。**/ public class DynamicDataSource extends AbstractRoutingDataSource{@Overrideprotected Object determineCurrentLookupKey() {// 使用DynamicDataSourceHolder保證線程安全,并且得到當前線程中的數據源keyreturn DynamicDataSourceHolder.getDataSourceKey();} }DynamicDataSourceHolder
使用ThreadLocal記錄數據源
/*** * 使用ThreadLocal技術來記錄當前線程中的數據源的key**/ public class DynamicDataSourceHolder {//寫庫對應的數據源keyprivate static final String MASTER = "master";//讀庫對應的數據源keyprivate static final String SLAVE = "slave";//使用ThreadLocal記錄當前線程的數據源keyprivate static final ThreadLocal<String> holder = new ThreadLocal<String>();/*** 設置數據源key* @param key*/public static void putDataSourceKey(String key) {holder.set(key);}/*** 獲取數據源key* @return*/public static String getDataSourceKey() {return holder.get();}/*** 標記寫庫*/public static void markMaster(){putDataSourceKey(MASTER);}/*** 標記讀庫*/public static void markSlave(){putDataSourceKey(SLAVE);} }DataSourceAspect
定義數據源的AOP切面
import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.JoinPoint;/*** 定義數據源的AOP切面,通過該Service的方法名判斷是應該走讀庫還是寫庫**/ public class DataSourceAspect {/*** 在進入Service方法之前執行* * @param point 切面對象*/public void before(JoinPoint point) {// 獲取到當前執行的方法名String methodName = point.getSignature().getName();if (isSlave(methodName)) {// 標記為讀庫DynamicDataSourceHolder.markSlave();} else {// 標記為寫庫DynamicDataSourceHolder.markMaster();}}/*** 判斷是否為讀庫* * @param methodName* @return*/private Boolean isSlave(String methodName) {// 方法名以query、find、get開頭的方法名走從庫return StringUtils.startsWithAny(methodName, "query", "find", "get");} }數據源
配置2個數據源
jdbc.properties
定義連接池
applicationContext.xml
<!-- 配置連接池 --> <bean id="masterDataSource" class="com.jolbox.bonecp.BoneCPDataSource"destroy-method="close"><!-- 數據庫驅動 --><property name="driverClass" value="${jdbc.master.driver}" /><!-- 相應驅動的jdbcUrl --><property name="jdbcUrl" value="${jdbc.master.url}" /><!-- 數據庫的用戶名 --><property name="username" value="${jdbc.master.username}" /><!-- 數據庫的密碼 --><property name="password" value="${jdbc.master.password}" /><!-- 檢查數據庫連接池中空閑連接的間隔時間,單位是分,默認值:240,如果要取消則設置為0 --><property name="idleConnectionTestPeriod" value="60" /><!-- 連接池中未使用的鏈接最大存活時間,單位是分,默認值:60,如果要永遠存活設置為0 --><property name="idleMaxAge" value="30" /><!-- 每個分區最大的連接數 --><property name="maxConnectionsPerPartition" value="150" /><!-- 每個分區最小的連接數 --><property name="minConnectionsPerPartition" value="5" /> </bean><!-- 配置連接池 --> <bean id="slave01DataSource" class="com.jolbox.bonecp.BoneCPDataSource"destroy-method="close"><!-- 數據庫驅動 --><property name="driverClass" value="${jdbc.slave01.driver}" /><!-- 相應驅動的jdbcUrl --><property name="jdbcUrl" value="${jdbc.slave01.url}" /><!-- 數據庫的用戶名 --><property name="username" value="${jdbc.slave01.username}" /><!-- 數據庫的密碼 --><property name="password" value="${jdbc.slave01.password}" /><!-- 檢查數據庫連接池中空閑連接的間隔時間,單位是分,默認值:240,如果要取消則設置為0 --><property name="idleConnectionTestPeriod" value="60" /><!-- 連接池中未使用的鏈接最大存活時間,單位是分,默認值:60,如果要永遠存活設置為0 --><property name="idleMaxAge" value="30" /><!-- 每個分區最大的連接數 --><property name="maxConnectionsPerPartition" value="150" /><!-- 每個分區最小的連接數 --><property name="minConnectionsPerPartition" value="5" /> </bean>DataSource
定義數據源
<!-- 定義數據源,使用自己實現的數據源 --> <bean id="dataSource" class="cn.itcast.usermanage.spring.DynamicDataSource"><!-- 設置多個數據源 --><property name="targetDataSources"><map key-type="java.lang.String"><!-- 這個key需要和程序中的key一致 --><entry key="master" value-ref="masterDataSource" /><entry key="slave" value-ref="slave01DataSource" /></map></property><!-- 設置默認的數據源,這里默認走寫庫 --><property name="defaultTargetDataSource" ref="masterDataSource" /> </bean>事務管理
定義事務管理器
<!-- 定義事務管理器 --> <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /> </bean>事務策略
定義事務策略
<!-- 定義事務策略 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--定義查詢方法都是只讀的 --><tx:method name="query*" read-only="true" /><tx:method name="find*" read-only="true" /><tx:method name="get*" read-only="true" /><!-- 主庫執行操作,事務傳播行為定義為默認行為 --><tx:method name="save*" propagation="REQUIRED" /><tx:method name="update*" propagation="REQUIRED" /><tx:method name="delete*" propagation="REQUIRED" /><!--其他方法使用默認事務策略 --><tx:method name="*" /></tx:attributes> </tx:advice>定義切面
自定義數據源在前面
先應該確定數據源,然后,開啟事務
確保,該切面在最前面
總結
以上是生活随笔為你收集整理的MySQL读写分离应用层实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL读写分离中间件解决
- 下一篇: MySQL读写分离事务策略实现