日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

在應(yīng)用層通過(guò)spring特性解決數(shù)據(jù)庫(kù)讀寫分離

系統(tǒng) 2031 0

?

如何配置mysql數(shù)據(jù)庫(kù)的主從?

單機(jī)配置 mysql 主從: http://my.oschina.net/god/blog/496

?

常見(jiàn)的解決數(shù)據(jù)庫(kù)讀寫分離有兩種方案

1 、應(yīng)用層

http://neoremind.net/2011/06/ spring 實(shí)現(xiàn)數(shù)據(jù)庫(kù)讀寫分離

目前的一些解決方案需要在程序中手動(dòng)指定數(shù)據(jù)源,比較麻煩,后邊我會(huì)通過(guò) AOP 思想來(lái)解決這個(gè)問(wèn)題。

?

2 、中間件

mysql-proxy http://hi.baidu.com/geshuai2008/item/0ded5389c685645f850fab07

Amoeba for?MySQL http://www.iteye.com/topic/188598 http://www.iteye.com/topic/1113437

?

此處我們介紹一種在應(yīng)用層的解決方案,通過(guò) spring 動(dòng)態(tài)數(shù)據(jù)源和 AOP 來(lái)解決數(shù)據(jù)庫(kù)的讀寫分離。

?

該方案目前已經(jīng)在一個(gè)互聯(lián)網(wǎng)項(xiàng)目中使用了,而且可以很好的工作。

?

該方案目前支持

一讀多寫;當(dāng)寫時(shí)默認(rèn)讀操作到寫庫(kù)、當(dāng)寫時(shí)強(qiáng)制讀操作到讀庫(kù)。

?

考慮未來(lái)支持

讀庫(kù)負(fù)載均衡、讀庫(kù)故障轉(zhuǎn)移等。

?

使用場(chǎng)景

不想引入中間件,想在應(yīng)用層解決讀寫分離,可以考慮這個(gè)方案;

建議數(shù)據(jù)訪問(wèn)層使用 jdbc ibatis ,不建議 hibernate。

?

優(yōu)勢(shì)

應(yīng)用層解決,不引入額外中間件;

在應(yīng)用層支持『當(dāng)寫時(shí)默認(rèn)讀操作到寫庫(kù)』,這樣如果我們采用這種方案,在寫操作后讀數(shù)據(jù)直接從寫庫(kù)拿,不會(huì)產(chǎn)生數(shù)據(jù)復(fù)制的延遲問(wèn)題;

應(yīng)用層解決讀寫分離,理論支持任意數(shù)據(jù)庫(kù)。

?

?

缺點(diǎn)

1、不支持@Transactional注解事務(wù),此方案要求所有讀方法必須是read-only=true,因此如果是@Transactional,這樣就要求在每一個(gè)讀方法頭上加@Transactional 且readOnly屬性=true,相當(dāng)麻煩。 :oops:?

2、必須按照配置約定進(jìn)行配置,不夠靈活。

?

兩種方案

在應(yīng)用層通過(guò)spring特性解決數(shù)據(jù)庫(kù)讀寫分離

方案 1 :當(dāng)只有讀操作的時(shí)候,直接操作讀庫(kù)(從庫(kù));

??????? 當(dāng)在寫事務(wù)(即寫主庫(kù))中讀時(shí),也是讀主庫(kù)(即參與到主庫(kù)操作),這樣的優(yōu)勢(shì)是可以防止寫完后可能讀不到剛才寫的數(shù)據(jù);

?

此方案其實(shí)是使用事務(wù)傳播行為為: SUPPORTS 解決的。

?


在應(yīng)用層通過(guò)spring特性解決數(shù)據(jù)庫(kù)讀寫分離

方案 2 :當(dāng)只有讀操作的時(shí)候,直接操作讀庫(kù)(從庫(kù));

??????? 當(dāng)在寫事務(wù)(即寫主庫(kù))中讀時(shí),強(qiáng)制走從庫(kù),即先暫停寫事務(wù),開啟讀(讀從庫(kù)),然后恢復(fù)寫事務(wù)。

此方案其實(shí)是使用事務(wù)傳播行為為: NOT_SUPPORTS 解決的。

?

核心組件

cn.javass.common.datasource.ReadWriteDataSource :讀寫分離的動(dòng)態(tài)數(shù)據(jù)源,類似于 AbstractRoutingDataSource ,具體參考 javadoc

cn.javass.common.datasource.ReadWriteDataSourceDecision :讀寫庫(kù)選擇的決策者,具體參考 javadoc

cn.javass.common.datasource.ReadWriteDataSourceProcessor :此類實(shí)現(xiàn)了兩個(gè)職責(zé)(為了減少類的數(shù)量將兩個(gè)功能合并到一起了):讀 / 寫動(dòng)態(tài)數(shù)據(jù)庫(kù)選擇處理器、通過(guò) AOP 切面實(shí)現(xiàn)讀 / 寫選擇,具體參考 javadoc

?

具體配置

1 、數(shù)據(jù)源配置

1.1 、寫庫(kù)配置

      	<bean id="writeDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
		<property name="alias" value="writeDataSource"/>
		<property name="driver" value="${write.connection.driver_class}" />
		<property name="driverUrl" value="${write.connection.url}" />
		<property name="user" value="${write.connection.username}" />
		<property name="password" value="${write.connection.password}" />
		<property name="maximumConnectionCount" value="${write.proxool.maximum.connection.count}"/>
		<property name="minimumConnectionCount" value="${write.proxool.minimum.connection.count}" />
		<property name="statistics" value="${write.proxool.statistics}" />
		<property name="simultaneousBuildThrottle" value="${write.proxool.simultaneous.build.throttle}"/>
	</bean>

  

?

1.2 、讀庫(kù)配置

        <bean id="readDataSource1" class="org.logicalcobwebs.proxool.ProxoolDataSource">
        <property name="alias" value="readDataSource"/>
        <property name="driver" value="${read.connection.driver_class}" />
        <property name="driverUrl" value="${read.connection.url}" />
        <property name="user" value="${read.connection.username}" />
        <property name="password" value="${read.connection.password}" />
        <property name="maximumConnectionCount" value="${read.proxool.maximum.connection.count}"/>
        <property name="minimumConnectionCount" value="${read.proxool.minimum.connection.count}" />
        <property name="statistics" value="${read.proxool.statistics}" />
        <property name="simultaneousBuildThrottle" value="${read.proxool.simultaneous.build.throttle}"/>
    </bean>?
  

1.3 、讀寫動(dòng)態(tài)庫(kù)配置 ???

通過(guò) writeDataSource 指定寫庫(kù),通過(guò) readDataSourceMap 指定從庫(kù)列表,從庫(kù)列表默認(rèn)通過(guò)順序輪詢來(lái)使用讀庫(kù),具體參考 javadoc

        <bean id="readWriteDataSource" class="cn.javass.common.datasource.ReadWriteDataSource">
        <property name="writeDataSource" ref="writeDataSource"/>
        <property name="readDataSourceMap">
           <map>
              <entry key="readDataSource1" value-ref="readDataSource1"/>
              <entry key="readDataSource2" value-ref="readDataSource1"/>
              <entry key="readDataSource3" value-ref="readDataSource1"/>
              <entry key="readDataSource4" value-ref="readDataSource1"/>
           </map>
        </property>
    </bean>?
  

?

2 XML 事務(wù)屬性配置

所以讀方法必須是 read-only (必須,以此來(lái)判斷是否是讀方法)。

        <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="merge*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            
            <tx:method name="put*" read-only="true"/>
            <tx:method name="query*" read-only="true"/>
            <tx:method name="use*" read-only="true"/>
            <tx:method name="get*" read-only="true" />
            <tx:method name="count*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="list*" read-only="true" />
            
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>?
  

?

3 、事務(wù)管理器

事務(wù)管理器管理的是 readWriteDataSource

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="readWriteDataSource"/>
    </bean>?
  

?

4 、讀 / 寫動(dòng)態(tài)數(shù)據(jù)庫(kù)選擇處理器

根據(jù)之前的 txAdvice 配置的事務(wù)屬性決定是讀 / 寫,具體參考 javadoc

forceChoiceReadWhenWrite :用于確定在如果目前是寫(即開啟了事務(wù)),下一步如果是讀,是直接參與到寫庫(kù)進(jìn)行讀,還是強(qiáng)制從讀庫(kù)讀,具體參考 javadoc

        <bean id="readWriteDataSourceTransactionProcessor" class="cn.javass.common.datasource.ReadWriteDataSourceProcessor">
       <property name="forceChoiceReadWhenWrite" value="false"/>
    </bean>?
  

?

5 、事務(wù)切面和讀 / 寫庫(kù)選擇切面

        <aop:config expose-proxy="true">
        <!-- 只對(duì)業(yè)務(wù)邏輯層實(shí)施事務(wù) -->
        <aop:pointcut id="txPointcut" expression="execution(* cn.javass..service..*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
        
        <!-- 通過(guò)AOP切面實(shí)現(xiàn)讀/寫庫(kù)選擇 -->
        <aop:aspect order="-2147483648" ref="readWriteDataSourceTransactionProcessor">
           <aop:around pointcut-ref="txPointcut" method="determineReadOrWriteDB"/>
        </aop:aspect>
    </aop:config>?
  

1 、事務(wù)切面一般橫切業(yè)務(wù)邏輯層;

2 、此處我們使用 readWriteDataSourceTransactionProcessor 的通過(guò) AOP 切面實(shí)現(xiàn)讀 / 寫庫(kù)選擇功能, order=Integer.MIN_VALUE( 即最高的優(yōu)先級(jí) ) ,從而保證在操作事務(wù)之前已經(jīng)決定了使用讀 / 寫庫(kù)。

?

6 、測(cè)試用例

只要配置好事務(wù)屬性(通過(guò)read-only=true指定讀方法)即可,其他選擇讀/寫庫(kù)的操作都交給readWriteDataSourceTransactionProcessor完成。

?

可以參考附件的:

cn.javass.readwrite.ReadWriteDBTestWithForceChoiceReadOnWriteFalse

cn.javass.readwrite.ReadWriteDBTestWithNoForceChoiceReadOnWriteTrue

?

?

可以下載附件的代碼進(jìn)行測(cè)試 ,具體選擇主 / 從可以參考日志輸出。

?

暫不想支持@Transactional注解式事務(wù)。

?

PS :歡迎拍磚指正。 ???

?

?

?

在應(yīng)用層通過(guò)spring特性解決數(shù)據(jù)庫(kù)讀寫分離


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 时尚| 天等县| 澜沧| 大名县| 丰都县| 类乌齐县| 克什克腾旗| 吉木乃县| 富民县| 吉安县| 邵阳县| 武陟县| 开封县| 卢龙县| 四会市| 尚志市| 绥阳县| 江阴市| 麻阳| 雷山县| 金秀| 佛学| 金门县| 城口县| 霍城县| 石台县| 临清市| 原阳县| 甘肃省| 寿阳县| 丹东市| 丽江市| 砚山县| 南乐县| 南投市| 楚雄市| 五原县| 江都市| 贵南县| 龙川县| 千阳县|