qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          數(shù)據(jù)庫Sharding的基本思想和切分策略

           本文著重介紹sharding的基本思想和理論上的切分策略,關(guān)于更加細(xì)致的實(shí)施策略和參考事例請參考我的另一篇博文:數(shù)據(jù)庫分庫分表(sharding)系列(一) 拆分實(shí)施策略和示例演示
            一、基本思想
            Sharding的基本思想就要把一個(gè)數(shù)據(jù)庫切分成多個(gè)部分放到不同的數(shù)據(jù)庫(server)上,從而緩解單一數(shù)據(jù)庫的性能問題。不太嚴(yán)格的講,對于海量數(shù)據(jù)的數(shù)據(jù)庫,如果是因?yàn)楸矶喽鴶?shù)據(jù)多,這時(shí)候適合使用垂直切分,即把關(guān)系緊密(比如同一模塊)的表切分出來放在一個(gè)server上。如果表并不多,但每張表的數(shù)據(jù)非常多,這時(shí)候適合水平切分,即把表的數(shù)據(jù)按某種規(guī)則(比如按ID散列)切分到多個(gè)數(shù)據(jù)庫(server)上。當(dāng)然,現(xiàn)實(shí)中更多是這兩種情況混雜在一起,這時(shí)候需要根據(jù)實(shí)際情況做出選擇,也可能會(huì)綜合使用垂直與水平切分,從而將原有數(shù)據(jù)庫切分成類似矩陣一樣可以無限擴(kuò)充的數(shù)據(jù)庫(server)陣列。下面分別詳細(xì)地介紹一下垂直切分和水平切分.
            垂直切分的最大特點(diǎn)就是規(guī)則簡單,實(shí)施也更為方便,尤其適合各業(yè)務(wù)之間的耦合度非常低,相互影響很小,業(yè)務(wù)邏輯非常清晰的系統(tǒng)。在這種系統(tǒng)中,可以很容易做到將不同業(yè)務(wù)模塊所使用的表分拆到不同的數(shù)據(jù)庫中。根據(jù)不同的表來進(jìn)行拆分,對應(yīng)用程序的影響也更小,拆分規(guī)則也會(huì)比較簡單清晰。(這也就是所謂的”share nothing”)。
            水平切分于垂直切分相比,相對來說稍微復(fù)雜一些。因?yàn)橐獙⑼粋€(gè)表中的不同數(shù)據(jù)拆分到不同的數(shù)據(jù)庫中,對于應(yīng)用程序來說,拆分規(guī)則本身就較根據(jù)表名來拆分更為復(fù)雜,后期的數(shù)據(jù)維護(hù)也會(huì)更為復(fù)雜一些。
            讓我們從普遍的情況來考慮數(shù)據(jù)的切分:一方面,一個(gè)庫的所有表通常不可能由某一張表全部串聯(lián)起來,這句話暗含的意思是,水平切分幾乎都是針對一小搓一小搓(實(shí)際上就是垂直切分出來的塊)關(guān)系緊密的表進(jìn)行的,而不可能是針對所有表進(jìn)行的。另一方面,一些負(fù)載非常高的系統(tǒng),即使僅僅只是單個(gè)表都無法通過單臺(tái)數(shù)據(jù)庫主機(jī)來承擔(dān)其負(fù)載,這意味著單單是垂直切分也不能完全解決問明。因此多數(shù)系統(tǒng)會(huì)將垂直切分和水平切分聯(lián)合使用,先對系統(tǒng)做垂直切分,再針對每一小搓表的情況選擇性地做水平切分。從而將整個(gè)數(shù)據(jù)庫切分成一個(gè)分布式矩陣。
            二、切分策略
            如前面所提到的,切分是按先垂直切分再水平切分的步驟進(jìn)行的。垂直切分的結(jié)果正好為水平切分做好了鋪墊。垂直切分的思路就是分析表間的聚合關(guān)系,把關(guān)系緊密的表放在一起。多數(shù)情況下可能是同一個(gè)模塊,或者是同一“聚集”。這里的“聚集”正是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)里所說的聚集。在垂直切分出的表聚集內(nèi),找出“根元素”(這里的“根元素”就是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)里的“聚合根”),按“根元素”進(jìn)行水平切分,也就是從“根元素”開始,把所有和它直接與間接關(guān)聯(lián)的數(shù)據(jù)放入一個(gè)shard里。這樣出現(xiàn)跨shard關(guān)聯(lián)的可能性就非常的小。應(yīng)用程序就不必打斷既有的表間關(guān)聯(lián)。比如:對于社交網(wǎng)站,幾乎所有數(shù)據(jù)最終都會(huì)關(guān)聯(lián)到某個(gè)用戶上,基于用戶進(jìn)行切分就是最好的選擇。再比如論壇系統(tǒng),用戶和論壇兩個(gè)模塊應(yīng)該在垂直切分時(shí)被分在了兩個(gè)shard里,對于論壇模塊來說,F(xiàn)orum顯然是聚合根,因此按Forum進(jìn)行水平切分,把Forum里所有的帖子和回帖都隨Forum放在一個(gè)shard里是很自然的。
            對于共享數(shù)據(jù)數(shù)據(jù),如果是只讀的字典表,每個(gè)shard里維護(hù)一份應(yīng)該是一個(gè)不錯(cuò)的選擇,這樣不必打斷關(guān)聯(lián)關(guān)系。如果是一般數(shù)據(jù)間的跨節(jié)點(diǎn)的關(guān)聯(lián),就必須打斷。
            需要特別說明的是:當(dāng)同時(shí)進(jìn)行垂直和水平切分時(shí),切分策略會(huì)發(fā)生一些微妙的變化。比如:在只考慮垂直切分的時(shí)候,被劃分到一起的表之間可以保持任意的關(guān)聯(lián)關(guān)系,因此你可以按“功能模塊”劃分表格,但是一旦引入水平切分之后,表間關(guān)聯(lián)關(guān)系就會(huì)受到很大的制約,通常只能允許一個(gè)主表(以該表ID進(jìn)行散列的表)和其多個(gè)次表之間保留關(guān)聯(lián)關(guān)系,也就是說:當(dāng)同時(shí)進(jìn)行垂直和水平切分時(shí),在垂直方向上的切分將不再以“功能模塊”進(jìn)行劃分,而是需要更加細(xì)粒度的垂直切分,而這個(gè)粒度與領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中的“聚合”概念不謀而合,甚至可以說是完全一致,每個(gè)shard的主表正是一個(gè)聚合中的聚合根!這樣切分下來你會(huì)發(fā)現(xiàn)數(shù)據(jù)庫分被切分地過于分散了(shard的數(shù)量會(huì)比較多,但是shard里的表卻不多),為了避免管理過多的數(shù)據(jù)源,充分利用每一個(gè)數(shù)據(jù)庫服務(wù)器的資源,可以考慮將業(yè)務(wù)上相近,并且具有相近數(shù)據(jù)增長速率(主表數(shù)據(jù)量在同一數(shù)量級上)的兩個(gè)或多個(gè)shard放到同一個(gè)數(shù)據(jù)源里,每個(gè)shard依然是獨(dú)立的,它們有各自的主表,并使用各自主表ID進(jìn)行散列,不同的只是它們的散列取模(即節(jié)點(diǎn)數(shù)量)必需是一致的。(本文著重介紹sharding的基本思想和理論上的切分策略,關(guān)于更加細(xì)致的實(shí)施策略和參考事例請參考我的另一篇博文:數(shù)據(jù)庫分庫分表(sharding)系列(一) 拆分實(shí)施策略和示例演示)
            1.事務(wù)問題:
            解決事務(wù)問題目前有兩種可行的方案:分布式事務(wù)和通過應(yīng)用程序與數(shù)據(jù)庫共同控制實(shí)現(xiàn)事務(wù)下面對兩套方案進(jìn)行一個(gè)簡單的對比。
            方案一:使用分布式事務(wù)
            優(yōu)點(diǎn):交由數(shù)據(jù)庫管理,簡單有效
            缺點(diǎn):性能代價(jià)高,特別是shard越來越多時(shí)
            方案二:由應(yīng)用程序和數(shù)據(jù)庫共同控制
            原理:將一個(gè)跨多個(gè)數(shù)據(jù)庫的分布式事務(wù)分拆成多個(gè)僅處
            于單個(gè)數(shù)據(jù)庫上面的小事務(wù),并通過應(yīng)用程序來總控
            各個(gè)小事務(wù)。
            優(yōu)點(diǎn):性能上有優(yōu)勢
            缺點(diǎn):需要應(yīng)用程序在事務(wù)控制上做靈活設(shè)計(jì)。如果使用
            了spring的事務(wù)管理,改動(dòng)起來會(huì)面臨一定的困難。
            2.跨節(jié)點(diǎn)Join的問題
            只要是時(shí)行切分,跨節(jié)點(diǎn)Join的問明是不可避免的。但是良好的設(shè)計(jì)和切分卻可以減少此類情況的發(fā)生。解決這一問題的普遍做法是分兩次查詢實(shí)現(xiàn)。在第一次查詢的結(jié)果集中找出關(guān)聯(lián)數(shù)據(jù)的id,根據(jù)這些id發(fā)起第二次請求得到關(guān)聯(lián)數(shù)據(jù)。
            3.跨節(jié)點(diǎn)的count,order by,group by以及聚合函數(shù)問題
            這些是一類問題,因?yàn)樗鼈兌夹枰谌繑?shù)據(jù)集合進(jìn)行計(jì)算。多數(shù)的代理都不會(huì)自動(dòng)處理合并工作。解決方案:與解決跨節(jié)點(diǎn)join問題的類似,分別在各個(gè)節(jié)點(diǎn)上得到結(jié)果后在應(yīng)用程序端進(jìn)行合并。和join不同的是每個(gè)結(jié)點(diǎn)的查詢可以并行執(zhí)行,因此很多時(shí)候它的速度要比單一大表快很多。但如果結(jié)果集很大,對應(yīng)用程序內(nèi)存的消耗是一個(gè)問題。

          posted on 2014-04-09 10:50 順其自然EVO 閱讀(597) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫linux

          <2014年4月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 吉隆县| 永靖县| 北安市| 白水县| 蓝田县| 夏邑县| 青海省| 新安县| 四川省| 鸡西市| 泰宁县| 醴陵市| 临沧市| 莎车县| 临夏县| 泸西县| 永宁县| 江津市| 蒙自县| 怀集县| 开化县| 台安县| 道真| 察哈| 萍乡市| 车致| 济宁市| 荥阳市| 龙胜| 永定县| 临泽县| 舒城县| 炉霍县| 海晏县| 南通市| 阳信县| 中方县| 上蔡县| 长沙县| 韶山市| 东乡县|