常見分片規(guī)則和策略

分片字段該如何選擇
在開始分片之前码倦,我們首先要確定分片字段(也可稱為“片鍵”)瞒瘸。很多常見的例子和場(chǎng)景中是采用ID或者時(shí)間字段進(jìn)行拆分论皆。這也并不絕對(duì)的,我的建議是結(jié)合實(shí)際業(yè)務(wù)假栓,通過對(duì)系統(tǒng)中執(zhí)行的sql語(yǔ)句進(jìn)行統(tǒng)計(jì)分析,選擇出需要分片的那個(gè)表中最頻繁被使用霍掺,或者最重要的字段來作為分片字段匾荆。
[

](https://www.atatech.org/articles/69032#4)常見分片規(guī)則
常見的分片策略有隨機(jī)分片和連續(xù)分片這兩種,如下圖所示:


當(dāng)需要使用分片字段進(jìn)行范圍查找時(shí)杆烁,連續(xù)分片可以快速定位分片進(jìn)行高效查詢牙丽,大多數(shù)情況下可以有效避免跨分片查詢的問題。后期如果想對(duì)整個(gè)分片集群擴(kuò)容時(shí)兔魂,只需要添加節(jié)點(diǎn)即可烤芦,無需對(duì)其他分片的數(shù)據(jù)進(jìn)行遷移。但是析校,連續(xù)分片也有可能存在數(shù)據(jù)熱點(diǎn)的問題构罗,就像圖中按時(shí)間字段分片的例子,有些節(jié)點(diǎn)可能會(huì)被頻繁查詢壓力較大智玻,熱數(shù)據(jù)節(jié)點(diǎn)就成為了整個(gè)集群的瓶頸遂唧。而有些節(jié)點(diǎn)可能存的是歷史數(shù)據(jù),很少需要被查詢到吊奢。
隨機(jī)分片其實(shí)并不是隨機(jī)的盖彭,也遵循一定規(guī)則。通常页滚,我們會(huì)采用Hash取模的方式進(jìn)行分片拆分召边,所以有些時(shí)候也被稱為離散分片。隨機(jī)分片的數(shù)據(jù)相對(duì)比較均勻裹驰,不容易出現(xiàn)熱點(diǎn)和并發(fā)訪問的瓶頸隧熙。但是,后期分片集群擴(kuò)容起來需要遷移舊的數(shù)據(jù)邦马。使用一致性Hash算法能夠很大程度的避免這個(gè)問題贱鼻,所以很多中間件的分片集群都會(huì)采用一致性Hash算法。離散分片也很容易面臨跨分片查詢的復(fù)雜問題滋将。
[

](https://www.atatech.org/articles/69032#5)數(shù)據(jù)遷移邻悬,容量規(guī)劃,擴(kuò)容等問題
很少有項(xiàng)目會(huì)在初期就開始考慮分片設(shè)計(jì)的随闽,一般都是在業(yè)務(wù)高速發(fā)展面臨性能和存儲(chǔ)的瓶頸時(shí)才會(huì)提前準(zhǔn)備父丰。因此,不可避免的就需要考慮歷史數(shù)據(jù)遷移的問題。一般做法就是通過程序先讀出歷史數(shù)據(jù)蛾扇,然后按照指定的分片規(guī)則再將數(shù)據(jù)寫入到各個(gè)分片節(jié)點(diǎn)中攘烛。
此外,我們需要根據(jù)當(dāng)前的數(shù)據(jù)量和QPS等進(jìn)行容量規(guī)劃镀首,綜合成本因素坟漱,推算出大概需要多少分片(一般建議單個(gè)分片上的單表數(shù)據(jù)量不要超過1000W)。
如果是采用隨機(jī)分片更哄,則需要考慮后期的擴(kuò)容問題芋齿,相對(duì)會(huì)比較麻煩。如果是采用的范圍分片成翩,只需要添加節(jié)點(diǎn)就可以自動(dòng)擴(kuò)容觅捆。
[

](https://www.atatech.org/articles/69032#6)跨分片技術(shù)問題
[

](https://www.atatech.org/articles/69032#7)跨分片的排序分頁(yè)
一般來講,分頁(yè)時(shí)需要按照指定字段進(jìn)行排序麻敌。當(dāng)排序字段就是分片字段的時(shí)候栅炒,我們通過分片規(guī)則可以比較容易定位到指定的分片,而當(dāng)排序字段非分片字段的時(shí)候术羔,情況就會(huì)變得比較復(fù)雜了赢赊。為了最終結(jié)果的準(zhǔn)確性,我們需要在不同的分片節(jié)點(diǎn)中將數(shù)據(jù)進(jìn)行排序并返回聂示,并將不同分片返回的結(jié)果集進(jìn)行匯總和再次排序域携,最后再返回給用戶。如下圖所示:


上面圖中所描述的只是最簡(jiǎn)單的一種情況(取第一頁(yè)數(shù)據(jù))鱼喉,看起來對(duì)性能的影響并不大秀鞭。但是,如果想取出第10頁(yè)數(shù)據(jù)扛禽,情況又將變得復(fù)雜很多锋边,如下圖所示:

有些讀者可能并不太理解,為什么不能像獲取第一頁(yè)數(shù)據(jù)那樣簡(jiǎn)單處理(排序取出前10條再合并编曼、排序)豆巨。其實(shí)并不難理解,因?yàn)楦鞣制?jié)點(diǎn)中的數(shù)據(jù)可能是隨機(jī)的掐场,為了排序的準(zhǔn)確性往扔,必須把所有分片節(jié)點(diǎn)的前N頁(yè)數(shù)據(jù)都排序好后做合并,最后再進(jìn)行整體的排序熊户。很顯然萍膛,這樣的操作是比較消耗資源的,用戶越往后翻頁(yè)嚷堡,系統(tǒng)性能將會(huì)越差蝗罗。
[

](https://www.atatech.org/articles/69032#8)跨分片的函數(shù)處理
在使用Max、Min、Sum串塑、Count之類的函數(shù)進(jìn)行統(tǒng)計(jì)和計(jì)算的時(shí)候沼琉,需要先在每個(gè)分片數(shù)據(jù)源上執(zhí)行相應(yīng)的函數(shù)處理,然后再將各個(gè)結(jié)果集進(jìn)行二次處理桩匪,最終再將處理結(jié)果返回打瘪。如下圖所示:


[

](https://www.atatech.org/articles/69032#9)跨分片join
Join是關(guān)系型數(shù)據(jù)庫(kù)中最常用的特性,但是在分片集群中傻昙,join也變得非常復(fù)雜瑟慈。應(yīng)該盡量避免跨分片的join查詢(這種場(chǎng)景,比上面的跨分片分頁(yè)更加復(fù)雜屋匕,而且對(duì)性能的影響很大)。通常有以下幾種方式來避免:
[

](https://www.atatech.org/articles/69032#10)全局表
全局表的概念之前在“垂直分庫(kù)”時(shí)提過借杰」牵基本思想一致,就是把一些類似數(shù)據(jù)字典又可能會(huì)產(chǎn)生join查詢的表信息放到各分片中蔗衡,從而避免跨分片的join纤虽。
[

](https://www.atatech.org/articles/69032#11)ER分片
在關(guān)系型數(shù)據(jù)庫(kù)中,表之間往往存在一些關(guān)聯(lián)的關(guān)系绞惦。如果我們可以先確定好關(guān)聯(lián)關(guān)系逼纸,并將那些存在關(guān)聯(lián)關(guān)系的表記錄存放在同一個(gè)分片上,那么就能很好的避免跨分片join問題济蝉。在一對(duì)多關(guān)系的情況下杰刽,我們通常會(huì)選擇按照數(shù)據(jù)較多的那一方進(jìn)行拆分。如下圖所示:


這樣一來王滤,Data Node1上面的訂單表與訂單詳細(xì)表就可以直接關(guān)聯(lián)贺嫂,進(jìn)行局部的join查詢了,Data Node2上也一樣雁乡〉谠基于ER分片的這種方式,能夠有效避免大多數(shù)業(yè)務(wù)場(chǎng)景中的跨分片join問題踱稍。
[

](https://www.atatech.org/articles/69032#12)內(nèi)存計(jì)算
隨著spark內(nèi)存計(jì)算的興起曲饱,理論上來講,很多跨數(shù)據(jù)源的操作問題看起來似乎都能夠得到解決珠月±┑恚可以將數(shù)據(jù)丟給spark集群進(jìn)行內(nèi)存計(jì)算,最后將計(jì)算結(jié)果返回桥温。
[

](https://www.atatech.org/articles/69032#13)跨分片事務(wù)問題
跨分片事務(wù)也分布式事務(wù)引矩,想要了解分布式事務(wù),就需要了解“XA接口”和“兩階段提交”。值得提到的是旺韭,MySQL5.5x和5.6x中的xa支持是存在問題的氛谜,會(huì)導(dǎo)致主從數(shù)據(jù)不一致。直到5.7x版本中才得到修復(fù)区端。Java應(yīng)用程序可以采用Atomikos框架來實(shí)現(xiàn)XA事務(wù)(J2EE中JTA)值漫。感興趣的讀者可以自行參考《分布式事務(wù)一致性解決方案》,鏈接地址:
http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency
[

](https://www.atatech.org/articles/69032#14)我們的系統(tǒng)真的需要分庫(kù)分表嗎
讀完上面內(nèi)容织盼,不禁引起有些讀者的思考杨何,我們的系統(tǒng)是否需要分庫(kù)分表嗎?
其實(shí)這點(diǎn)沒有明確的判斷標(biāo)準(zhǔn)沥邻,比較依賴實(shí)際業(yè)務(wù)情況和經(jīng)驗(yàn)判斷危虱。依照筆者個(gè)人的經(jīng)驗(yàn),一般MySQL單表1000W左右的數(shù)據(jù)是沒有問題的(前提是應(yīng)用系統(tǒng)和數(shù)據(jù)庫(kù)等層面設(shè)計(jì)和優(yōu)化的比較好)唐全。當(dāng)然埃跷,除了考慮當(dāng)前的數(shù)據(jù)量和性能情況時(shí)沦寂,作為架構(gòu)師典唇,我們需要提前考慮系統(tǒng)半年到一年左右的業(yè)務(wù)增長(zhǎng)情況,對(duì)數(shù)據(jù)庫(kù)服務(wù)器的QPS缨叫、連接數(shù)延届、容量等做合理評(píng)估和規(guī)劃剪勿,并提前做好相應(yīng)的準(zhǔn)備工作。如果單機(jī)無法滿足方庭,且很難再?gòu)钠渌矫鎯?yōu)化厕吉,那么說明是需要考慮分片的。這種情況可以先去掉數(shù)據(jù)庫(kù)中自增ID械念,為分片和后面的數(shù)據(jù)遷移工作提前做準(zhǔn)備赴涵。
很多人覺得“分庫(kù)分表”是宜早不宜遲,應(yīng)該盡早進(jìn)行订讼,因?yàn)閾?dān)心越往后公司業(yè)務(wù)發(fā)展越快髓窜、系統(tǒng)越來越復(fù)雜、系統(tǒng)重構(gòu)和擴(kuò)展越困難…這種話聽起來是有那么一點(diǎn)道理欺殿,但我的觀點(diǎn)恰好相反寄纵,對(duì)于關(guān)系型數(shù)據(jù)庫(kù)來講,我認(rèn)為“能不分片就別分片”脖苏,除非是系統(tǒng)真正需要程拭,因?yàn)閿?shù)據(jù)庫(kù)分片并非低成本或者免費(fèi)的。
這里筆者推薦一個(gè)比較靠譜的過渡技術(shù)–“表分區(qū)”棍潘。主流的關(guān)系型數(shù)據(jù)庫(kù)中基本都支持恃鞋。不同的分區(qū)在邏輯上仍是一張表崖媚,但是物理上卻是分開的,能在一定程度上提高查詢性能恤浪,而且對(duì)應(yīng)用程序透明畅哑,無需修改任何代碼。筆者曾經(jīng)負(fù)責(zé)優(yōu)化過一個(gè)系統(tǒng)水由,主業(yè)務(wù)表有大約8000W左右的數(shù)據(jù)荠呐,考慮到成本問題,當(dāng)時(shí)就是采用“表分區(qū)”來做的砂客,效果比較明顯泥张,且系統(tǒng)運(yùn)行的很穩(wěn)定。
[

](https://www.atatech.org/articles/69032#15)小結(jié)
最后鞠值,有很多讀者都想了解當(dāng)前社區(qū)中有沒有開源免費(fèi)的分庫(kù)分表解決方案媚创,畢竟站在巨人的肩膀上能省力很多。當(dāng)前主要有幾類解決方案:
基于應(yīng)用程序?qū)用娴腄DAL(分布式數(shù)據(jù)庫(kù)訪問層)
比較典型的就是淘寶半開源的TDDL彤恶,當(dāng)當(dāng)網(wǎng)開源的Sharding-JDBC等筝野。分布式數(shù)據(jù)訪問層無需硬件投入,技術(shù)能力較強(qiáng)的大公司通常會(huì)選擇自研或參照開源框架進(jìn)行二次開發(fā)和定制粤剧。對(duì)應(yīng)用程序的侵入性一般較大,會(huì)增加技術(shù)成本和復(fù)雜度挥唠。通常僅支持特定編程語(yǔ)言平臺(tái)(Java平臺(tái)的居多)抵恋,或者僅支持特定的數(shù)據(jù)庫(kù)和特定數(shù)據(jù)訪問框架技術(shù)(一般支持MySQL數(shù)據(jù)庫(kù),JDBC宝磨、MyBatis弧关、Hibernate等框架技術(shù))。

數(shù)據(jù)庫(kù)中間件唤锉,比較典型的像mycat(在阿里開源的cobar基礎(chǔ)上做了很多優(yōu)化和改進(jìn)世囊,屬于后起之秀,也支持很多新特性)窿祥,基于Go語(yǔ)言實(shí)現(xiàn)kingSharding株憾,比較老牌的Atlas(由360開源)等。這些中間件在互聯(lián)網(wǎng)企業(yè)中大量被使用晒衩。另外嗤瞎,MySQL 5.x企業(yè)版中官方提供的Fabric組件也號(hào)稱支持分片技術(shù),不過國(guó)內(nèi)使用的企業(yè)較少听系。
中間件也可以稱為“透明網(wǎng)關(guān)”贝奇,大名鼎鼎的mysql_proxy大概是該領(lǐng)域的鼻祖(由MySQL官方提供,僅限于實(shí)現(xiàn)“讀寫分離”)靠胜。中間件一般實(shí)現(xiàn)了特定數(shù)據(jù)庫(kù)的網(wǎng)絡(luò)通信協(xié)議掉瞳,模擬一個(gè)真實(shí)的數(shù)據(jù)庫(kù)服務(wù)毕源,屏蔽了后端真實(shí)的Server,應(yīng)用程序通常直接連接中間件即可陕习。而在執(zhí)行SQL操作時(shí)霎褐,中間件會(huì)按照預(yù)先定義分片規(guī)則,對(duì)SQL語(yǔ)句進(jìn)行解析衡查、路由瘩欺,并對(duì)結(jié)果集做二次計(jì)算再最終返回。引入數(shù)據(jù)庫(kù)中間件的技術(shù)成本更低拌牲,對(duì)應(yīng)用程序來講侵入性幾乎沒有俱饿,可以滿足大部分的業(yè)務(wù)。增加了額外的硬件投入和運(yùn)維成本塌忽,同時(shí)拍埠,中間件自身也存在性能瓶頸和單點(diǎn)故障問題,需要能夠保證中間件自身的高可用土居、可擴(kuò)展枣购。

采用云平臺(tái),例如:阿里云DRDS

總之擦耀,不管是使用分布式數(shù)據(jù)訪問層還是數(shù)據(jù)庫(kù)中間件棉圈,都會(huì)帶來一定的成本和復(fù)雜度,也會(huì)有一定的性能影響眷蜓。所以分瘾,還需讀者根據(jù)實(shí)際情況和業(yè)務(wù)發(fā)展需要慎重考慮和選擇。如果業(yè)務(wù)確實(shí)需要吁系,但技術(shù)實(shí)力又不夠德召,那么優(yōu)先考慮阿里云DRDS吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末汽纤,一起剝皮案震驚了整個(gè)濱河市上岗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蕴坪,老刑警劉巖肴掷,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異背传,居然都是意外死亡捆等,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門续室,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栋烤,“玉大人,你說我怎么就攤上這事挺狰∶鞴” “怎么了买窟?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)薯定。 經(jīng)常有香客問我始绍,道長(zhǎng),這世上最難降的妖魔是什么话侄? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任亏推,我火速辦了婚禮,結(jié)果婚禮上年堆,老公的妹妹穿的比我還像新娘吞杭。我一直安慰自己,他們只是感情好变丧,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布芽狗。 她就那樣靜靜地躺著,像睡著了一般痒蓬。 火紅的嫁衣襯著肌膚如雪童擎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天攻晒,我揣著相機(jī)與錄音顾复,去河邊找鬼。 笑死鲁捏,一個(gè)胖子當(dāng)著我的面吹牛芯砸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碴萧,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼末购!你這毒婦竟也來了破喻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤盟榴,失蹤者是張志新(化名)和其女友劉穎曹质,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擎场,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡羽德,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迅办。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宅静。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖站欺,靈堂內(nèi)的尸體忽然破棺而出姨夹,到底是詐尸還是另有隱情纤垂,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布磷账,位于F島的核電站峭沦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏逃糟。R本人自食惡果不足惜吼鱼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绰咽。 院中可真熱鬧菇肃,春花似錦、人聲如沸剃诅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)矛辕。三九已至笑跛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間聊品,已是汗流浹背飞蹂。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翻屈,地道東北人陈哑。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像伸眶,于是被迫代替她去往敵國(guó)和親惊窖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容