欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

數(shù)據(jù)訪問中的多數(shù)據(jù)源(Multi-DataSource in Dat

系統(tǒng) 2231 0

在實際的項目中,我們很少就使用一個數(shù)據(jù)庫,出于災(zāi)難恢復(fù)或者負載均衡之類目的考慮,生產(chǎn)環(huán)境中通常都會存在多臺數(shù)據(jù)庫服務(wù)器,相應(yīng)的,在應(yīng)用程序?qū)@些數(shù)據(jù)庫進行數(shù)據(jù)訪問的時候, 我們通常就會碰到一個比較常見的問題,即如何管理數(shù)據(jù)訪問過程中牽扯的多個數(shù)據(jù)源。

下面我們不妨從兩個角度來闡述一下在應(yīng)用程序中如何對多個數(shù)據(jù)源進行管理…

4.4.2.1. “ 主權(quán)獨立 ”的多數(shù)據(jù)源

所謂“ 主權(quán)獨立 ”是指系統(tǒng)中的每一個數(shù)據(jù)源都對外獨立承擔暴露數(shù)據(jù)庫資源的職能:

具體的應(yīng)用場景可能是:

  • 每一個數(shù)據(jù)庫所存儲的數(shù)據(jù)性質(zhì)不同,比如數(shù)據(jù)庫A存儲重要的交易信息,數(shù)據(jù)庫B存儲次要的系統(tǒng)管理 信息等等, 如果要訪問交易信息,那么通常可以明確指定使用對應(yīng)數(shù)據(jù)庫A的dataSourceA進行數(shù)據(jù)訪問;如果要訪問系統(tǒng)管理信息,則明確指定使用對應(yīng)數(shù)據(jù)庫B 的dataSourceB,其他依次類推。
  • 每一個數(shù)據(jù)庫分別承擔不同的數(shù)據(jù)訪問請求形式,比如數(shù)據(jù)庫A只允許更新操作不允許查詢,數(shù)據(jù)庫B只允許查詢不允許更新等, 這個時候,也是可以明確指定使用哪一個dataSource進行數(shù)據(jù)訪問;

當然,類似的場景并非只有這些,但總的意圖是相似的,那就是每一個dataSource的職能對于使用它們的客戶端來說足夠明確,完全是各自獨立使 用。 筆者經(jīng)歷的FX項目中就使用了這樣的多數(shù)據(jù)源管理方式。在FX中,設(shè)置的MAIN數(shù)據(jù)庫主要存儲顧客或者銀行與FX Broker之間的交易信息,設(shè)置的INFO數(shù)據(jù)庫主要存儲匯率以及系統(tǒng)履歷之類的信息 [ 32 ] 。 通常情況下,針對交易以及匯率之間的信息存儲在邏輯上是可以分開進行的,所以現(xiàn)在,應(yīng)用程序?qū)?yīng)的spring配置內(nèi)容基本如下:

        <bean id="mainDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 <property name="url" value="${main.jdbcUrl}"/>
 <property name="driverClassName" value="${main.driver}"/>
 <property name="username" value="${main.username}"/>
 <property name="password" value="${main.passwork}"/>
 <!-- other property settings -->
</bean>

<bean id="infoDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 <property name="url" value="${info.jdbcUrl}"/>
 <property name="driverClassName" value="${info.driver}"/>
 <property name="username" value="${info.username}"/>
 <property name="password" value="${info.password}"/>
 <!-- other property settings -->
</bean>

<bean id="mainJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 <property name="dataSource" ref="mainDataSource"/>
</bean>

<bean id="infoJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 <property name="dataSource" ref="infoDataSource"/>
</bean>

<bean id="dataAccessResourceSupport" abstract="true">
 <property name="mainJdbcTemplate" ref=""/>
 <property name="infoJdbcTemplate" ref=""/>
</bean>

<bean id="someDaoWithMainDS" class="...">
 <property name="mainJdbcTemplate" ref="mainJdbcTemplate"/>
 <!-- other property settings -->
</bean>

<bean id="someDaoWithInfoDS" class="...">
 <property name="infoJdbcTemplate" ref="infoJdbcTemplate"/>
 <!-- other property settings -->
</bean>

<bean id="someDaoWithBothDS" class="..." parent="dataAccessResourceSupport">
 <!-- other property settings -->
</bean>
      

項目中這種情況下的多數(shù)據(jù)源管理是最簡單的,也是比較容易管理的方式,所以,在你考慮下面將要談到的這種更加動態(tài),更加復(fù)雜的多數(shù)據(jù)源管理方式之 前, 請先對你的數(shù)據(jù)訪問場景做一個評估,看一下當前這種方式是否已經(jīng)足夠滿足項目的數(shù)據(jù)訪問需要,實在不行的話,再考慮后繼方案,也就是在運行期間來決定到底 使用多個數(shù)據(jù)源中的哪一個。

4.4.2.2. “ 合縱連橫 ”的多數(shù)據(jù)源

社區(qū)中經(jīng)常提到的“ 多數(shù)據(jù)源互換 ”即屬于這種場景,之所以用“ 合縱連橫 ”來形容這些數(shù)據(jù)源是因為,對于使用它們的數(shù)據(jù)訪問類來說, 這些數(shù)據(jù)源已經(jīng)喪失了“ 獨立自主 ”的地位,所有與數(shù)據(jù)訪問類進行的交互需要通過“ 盟主 ”進行,該盟主本質(zhì)上也是一個DataSource, 但它的職責更加傾向于對“ 聯(lián)盟 ”內(nèi)的多個DataSource的職能進行協(xié)調(diào)和管理,最終數(shù)據(jù)訪問所需要的資源由“ 盟主 ”來決定要哪一個DataSource貢獻出來。

使用這種多數(shù)據(jù)源管理方式的具體場景可能有:

  • 系統(tǒng)中設(shè)置多臺“ 地位相當 ”的數(shù)據(jù)庫以實現(xiàn)多機熱備,從而保證數(shù)據(jù)庫的高可用性(HA,High Availability),這個時候,如果某一臺數(shù)據(jù)庫掛掉的話, 可以迅速切換到另一臺數(shù)據(jù)庫,而對于數(shù)據(jù)訪問類來說,這樣的切換對其是透明的;
  • 系統(tǒng)中存在的多臺服務(wù)器也是“ 地位相當 ” 的,不過,同一時間他們都處于活動(Active)狀態(tài),處于負載均衡等因素考慮,數(shù)據(jù)訪問請求需要在這幾臺數(shù)據(jù)庫服務(wù)器之間進行合理分配, 這個時候,通過統(tǒng)一的一個DataSource來屏蔽這種請求分配的需求,從而屏蔽數(shù)據(jù)訪問類與具體DataSource的耦合;
  • 系統(tǒng)中存在的多臺數(shù)據(jù)庫服務(wù)器現(xiàn)在地位可能相當也可能不相當,但數(shù)據(jù)訪問類在系統(tǒng)啟動時間無法明確到底應(yīng)該使用哪一個數(shù)據(jù)源進行數(shù)據(jù)訪問,而必須在系統(tǒng)運行期間通過某種條件來判定到底應(yīng)該使用哪一個數(shù)據(jù)源, 這個時候,我們也得使用這種“ 合縱連橫 ”的方式向數(shù)據(jù)訪問類暴露一個統(tǒng)一的DataSource,由該DataSource來解除數(shù)據(jù)訪問類與具體數(shù)據(jù)源之間的過緊耦合;

更多場景需要讀者根據(jù)具體的應(yīng)用來判定,不過,并非所有的應(yīng)用要做這樣的處理,如果能夠保持簡單,那盡量保持簡單,畢竟,我們提倡K.I.S.S.(Keep It Simple,Stupid)嘛! 要實現(xiàn)這種“ 合縱連和 ” 的多數(shù)據(jù)源管理方式,總的指導(dǎo)原則就是實現(xiàn)一個自定義的DataSource,讓該DataSource來管理系統(tǒng)中存在的多個與具體數(shù)據(jù)庫掛鉤的數(shù)據(jù) 源, 數(shù)據(jù)訪問類只跟這個自定義的DataSource打交道即可。在spring2.0.1發(fā)布之前,各個項目中可能存在多種針對這種情況下的多數(shù)據(jù)源管理方 式, 不過,spring2.0.1發(fā)布之后,引入了AbstractRoutingDataSource,使用該類可以實現(xiàn)普遍意義上的多數(shù)據(jù)源管理功能。

假設(shè)我們有三臺數(shù)據(jù)庫用來實現(xiàn)負載均衡,所有的數(shù)據(jù)訪問請求最終需要平均的分配到這三臺數(shù)據(jù)庫服務(wù)器之上,那么,我們可以通過繼承AbstractRoutingDataSource來快速實現(xiàn)一個滿足這樣場景的原型(Prototype):

        public class PrototypeLoadBalanceDataSource extends AbstractRoutingDataSource  {

 private Lock            lock = new ReentrantLock();
 private int          counter = 0;
 private int dataSourceNumber = 3;

 @Override
 protected Object determineCurrentLookupKey() {
  lock.lock();
  try
  {
   counter++;
   int lookupKey = counter % getDataSourceNumber();
   return new Integer(lookupKey);
  }
  finally
  {
   lock.unlock();
  }
 }
 // ...
}
      

我們在介紹AbstractRoutingDataSource的時候說過,要繼承該類,通常只需要給出determineCurrentLookupKey()方法的邏輯即可。 下面是針對PrototypeLoadBalanceDataSource的配置:

        <bean id="dataSourc1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 <property name="url" value=".."/>
 <property name="driverClassName" value=".."/>
 <property name="username" value=".."/>
 <property name="password" value=".."/>
 <!-- other property settings -->
</bean>

<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 <property name="url" value=".."/>
 <property name="driverClassName" value=".."/>
 <property name="username" value=".."/>
 <property name="password" value=".."/>
 <!-- other property settings -->
</bean>

<bean id="dataSource3" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 <property name="url" value=".."/>
 <property name="driverClassName" value=".."/>
 <property name="username" value=".."/>
 <property name="password" value=".."/>
 <!-- other property settings -->
</bean>

<util:map id="dataSources">
 <entry key="0" value-ref="dataSource1"/>
 <entry key="1" value-ref="dataSource2"/>
 <entry key="2" value-ref="dataSource3"/>
</util:map>

<bean id="dataSourceLookup" class="org.springframework.jdbc.datasource.lookup.MapDataSourceLookup">
 <constructor-arg>
  <ref bean="dataSources"/>
 </constructor-arg>
</bean>

<bean id="dataSource" class="..PrototypeLoadBalanceDataSource">
 <property name="defaultTargetDataSource" ref="dataSourc1"/>
 <property name="targetDataSources" ref="dataSources"/>
 <property name="dataSourceLookup" ref=""/>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="someDao" class="...">
 <property name=""jdbcTemplate"" ref=""jdbcTemplate""/>
 <!-- other property settings -->
</bean>
      

因為我們不想使用AbstractRoutingDataSource的默認鍵值(Key)查找行為(根據(jù)指定的鍵值(Key)通過JNDI進行查 找), 所以,我們?yōu)镻rototypeLoadBalanceDataSource重新設(shè)置了DataSourceLookup,轉(zhuǎn)而使用 MapDataSourceLookup。

Tip

在PrototypeLoadBalanceDataSource中,我們直接將查找的鍵值(Key)寫死到了代碼中,實際上,更多時候,我們會將 鍵值 (Key)綁定到當前線程上,而determineCurrentLookupKey()方法內(nèi)直接從當前線程取得綁定的Key返回即可。 而這種情況下對Key的更改也變得更加靈活多變,比如,我可以在數(shù)據(jù)訪問類內(nèi)直接將我要訪問的數(shù)據(jù)源對應(yīng)的查找Key綁定到當前線程,我也可以在系統(tǒng)的某 個位置設(shè)置攔截器(Interceptor),當攔截到相應(yīng)事件的時候,根據(jù)邏輯設(shè)置綁定到當前線程的查找鍵值(Key)等等。 讀者可以先思考如果讓你來實現(xiàn)這么一個AbstractRoutingDataSource,你應(yīng)該如何處理。不過,如果你已經(jīng)迫不及待,那可以直接轉(zhuǎn)向 spring的事務(wù)管理一章的擴展篇,我將在那里為你展示詳細的實現(xiàn)過程。

有了AbstractRoutingDataSource之后,實現(xiàn)這種“ 合縱連橫 ”的多數(shù)據(jù)源管理,將不再像最初看起來那么復(fù)雜而神秘。

4.4.2.3. 結(jié)束語

因為以上兩種多數(shù)據(jù)源的管理方式在實際的使用過程中可能還有一些變數(shù),所以,最后筆者還是覺得應(yīng)該提及兩點:

  • 不管是“ 獨立主權(quán) ”的多數(shù)據(jù)源管理方式還是“ 合縱連橫 ”的多數(shù)據(jù)源管理方式, 單獨使用任何一種都是有其特定的應(yīng)用場景的,不過,這并不意味著二者是相互競爭甚至割裂的,實際上,如果必要,我們完全可以組合兩種多數(shù)據(jù)源管理方式。
    如果我們將“ 合縱連橫 ”的多數(shù)據(jù)源作為一個整體放入“ 獨立主權(quán) ”的多數(shù)據(jù)源場景中的話,我們可以得到如下的一幅畫卷:

    ?

    Figure 4.11. “ 合縱連橫 ”爭取“ 主權(quán)獨立

    如果我們將“ 獨立主權(quán) ”的多個數(shù)據(jù)源先分別注入上一層對象,然后將上一層對象和數(shù)據(jù)源作為一個整體再并入“ 合縱連橫 ”的多數(shù)據(jù)源場景的話,那么,我們又可以得出另一幅圖景:

    Figure 4.12. 從“ 主權(quán)獨立 ”并入“ 合縱連橫

    當然,如果愿意,你還可以根據(jù)情況采取進一步的組合措施,不過,在進行之前,還是需要你首先全面評估一下整體情況,看是否真的需要這么做,畢竟,復(fù)雜度的過多引入有些時候并非必要的。

  • 在“ 主權(quán)獨立 ”的多數(shù)據(jù)源場景中,我們是將獨立的數(shù)據(jù)源注入給了JdbcTemplate,但這只是為了演示的目的,實際上,對于IBatis以及Hibernate來說, 這樣的場景也是類似的;不過,在“ 合縱連橫 ”的多數(shù)據(jù)源場景中,將JdbcTemplate的使用類推IBatis,即SqlMapClientTemplate,是可以的,但以同樣的方式類推到Hibernate則有需要注意的地方。 我們可以將“ 合縱連橫 ” 的多個數(shù)據(jù)源注入給Hibernate的SessionFactory(實際上是通過Spring的LocalSessionFactoryBean), 然后HibernateTemplate直接引用這個SessionFactory即可, 但當你開啟了Hibernate的二級緩存的時候(與SessionFactory掛鉤),這樣的多個數(shù)據(jù)源直接注入SessionFactory并且可 以動態(tài)查找替換的方式可能造成問題。 如果二級緩存中有與當前使用的DataSource掛鉤的內(nèi)容,而這個時候切換到了下一個DataSource,那么二級緩存里的內(nèi)容需要你根據(jù)情況進行 合理的處理,或者清空,或者通過某種方式來同步, 否則在并發(fā)的情況下,難免出現(xiàn)問題,當然啦,如果你可以忽略這樣的數(shù)據(jù)沖突,那可能也有不處理的理由。如果你不需要開啟Hibernate的二級緩存,或 者可以和略二級緩存數(shù)據(jù)的不一致性,那么,采用“ 合縱連橫 ”的多數(shù)據(jù)源直接注入使用的SessionFactory的方式實現(xiàn)多個數(shù)據(jù)源的管理是可以的; 否則的話,可以將“ 獨立主權(quán) ”的多數(shù)據(jù)源管理方式并入“ 合縱連橫 ” 的多數(shù)據(jù)源管理方式,以SessionFactory一級替代DataSource一級,這也就是第二種組合場景所描繪的那樣。 這個時候,你可以像Spring提供AbstractRoutingDataSource那樣,提供一個 AbstractRoutingSessionFactory,也可以自己實現(xiàn)一個SessionFactory來屏蔽多個具體的 SessionFactory, 總之方法和原則跟多個數(shù)據(jù)源的處理方式是類似的,至于你要采用設(shè)計模式還是AOP,那就看你的啦!

最后,祝各位在多數(shù)據(jù)源管理的道路上一帆風順,即使不順,那么應(yīng)用以上的方式“ 排除萬難去爭取勝利 ”也不再是難事了吧?!

數(shù)據(jù)訪問中的多數(shù)據(jù)源(Multi-DataSource in Data Access)


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 精品欧美一区二区三区久久久小说 | 玖玖精品视频在线观看 | 中文字幕在线免费观看 | 精品中文字幕在线观看 | 亚洲十欧美十日韩十国产 | 青草视频网址 | 久久久久久久99精品免费观看 | jzz 护士| 91久久国产精品 | 久久人人精品 | 天天操网 | 久操欧美 | 免费国产一区二区在免费观看 | 国产高清无专砖区2021 | 福利入口在线观看 | 亚洲成人av一区二区 | 久久伊人一区二区三区四区 | 精品综合网| 成人久久久 | 精品免费久久久久久成人影院 | 国产精品久久久久一区二区 | 日韩在线免费播放 | 麻豆专区一区二区三区四区五区 | 久久久免费的精品 | 日韩a在线 | www色网站 | 色就干| 91精品国产91久久久久久 | 波多野结衣全部系列在线观看 | 91视频苹果版 | 九九热视频这里只有精品 | 成人 日韩 | 色呦呦在线免费观看 | 国产成人免费永久播放视频平台 | 亚洲美女黄色 | 午夜精品久久久久久久星辰影院 | 中国免费看的片 | 日日干夜夜干 | 亚洲成人av | av在线播放亚洲 | 中文字幕免费 |