數據庫水平切分的實現(xiàn)原理解析——分庫,分表讳推,主從顶籽,集群,負載均衡器(轉)

http://www.cnblogs.com/zhongxinWang/p/4262650.html

第1章 引言

隨著互聯(lián)網應用的廣泛普及银觅,海量數據的存儲和訪問成為了系統(tǒng)設計的瓶頸問題礼饱。對于一個大型的互聯(lián)網應用,每天幾十億的PV無疑對數據庫造成了相當高的負載究驴。對于系統(tǒng)的穩(wěn)定性和擴展性造成了極大的問題镊绪。通過數據切分來提高網站性能,橫向擴展數據層已經成為架構研發(fā)人員首選的方式洒忧。

  • 水平切分數據庫:可以降低單臺機器的負載蝴韭,同時最大限度的降低了宕機造成的損失;

  • 負載均衡策略:可以降低單臺機器的訪問負載熙侍,降低宕機的可能性榄鉴;

  • 集群方案:解決了數據庫宕機帶來的單點數據庫不能訪問的問題;

  • 讀寫分離策略:最大限度了提高了應用中讀取數據的速度和并發(fā)量蛉抓;

第2章 基本原理和概念

什么是數據切分

"Shard" 這個詞英文的意思是"碎片"庆尘,而作為數據庫相關的技術用語,似乎最早見于大型多人在線角色扮演游戲中巷送。"Sharding" 姑且稱之為"分片"减余。Sharding 不是一個某個特定數據庫軟件附屬的功能,而是在具體技術細節(jié)之上的抽象處理惩系,是水平擴展(Scale Out位岔,亦或橫向擴展、向外擴展)的解決方案堡牡,

其主要目的是為突破單節(jié)點數據庫服務器的 I/O 能力限制抒抬,解決數據庫擴展性問題。

通過一系列的切分規(guī)則將數據水平分布到不同的DB或table中晤柄,在通過相應的DB路由或者table路由規(guī)則找到需要查詢的具體的DB或者table擦剑,以進行Query操作〗婢保“sharding”通常是指“水平切分”惠勒,這也是本文討論的重點。接下來舉個簡單的例子:我們針對一個Blog應用中的日志來說明爬坑,比如日志文章(article)表有如下字段:

image

面對這樣的一個表纠屋,我們怎樣切分呢?怎樣將這樣的數據分布到不同的數據庫中的表中去呢盾计?我們可以這樣做售担,將user_id為1~10000的所有的文章信息放入DB1中的article表中赁遗,將user_id為10001~20000的所有文章信息放入DB2中的 article表中,以此類推族铆,一直到DBn岩四。這樣一來,文章數據就很自然的被分到了各個數據庫中哥攘,達到了數據切分的目的剖煌。

接下來要解決的問題就是怎樣找到具體的數據庫呢?其實問題也是簡單明顯的逝淹,既然分庫的時候我們用到了區(qū)分字段user_id末捣,那么很自然,數據庫路由的過程當然還是少不了user_id的创橄。就是我們知道了這個blog的user_id箩做,就利用這個user_id,利用分庫時候的規(guī)則妥畏,反過來定位具體的數據庫邦邦。比如user_id是234,利用剛才的規(guī)則醉蚁,就應該定位到DB1燃辖,假如user_id是12343,利用該才的規(guī)則网棍,就應該定位到DB2黔龟。以此類推,利用分庫的規(guī)則滥玷,反向的路由到具體的DB氏身,這個過程我們稱之為“

DB路由

”。

平常我們會自覺的按照范式來設計我們的數據庫惑畴,考慮到數據切分的DB設計蛋欣,將違背這個通常的規(guī)矩和約束。為了切分如贷,我們不得不在數據庫的表中出現(xiàn)冗余字段陷虎,用作區(qū)分字段或者叫做分庫的標記字段。比如上面的article的例子中的user_id這樣的字段(當然杠袱,剛才的例子并沒有很好的體現(xiàn)出user_id的冗余性尚猿,因為user_id這個字段即使就是不分庫,也是要出現(xiàn)的楣富,算是我們撿了便宜吧)凿掂。當然冗余字段的出現(xiàn)并不只是在分庫的場景下才出現(xiàn)的,在很多大型應用中菩彬,冗余也是必須的缠劝,這個涉及到高效DB的設計潮梯,本文不再贅述骗灶。

為什么要數據切分

上面對什么是數據切分做了個概要的描述和解釋惨恭,讀者可能會疑問,為什么需要數據切分呢耙旦?像 Oracle這樣成熟穩(wěn)定的數據庫脱羡,足以支撐海量數據的存儲與查詢了?為什么還需要數據切片呢免都?

的確锉罐,Oracle的DB確實很成熟很穩(wěn)定,但是高昂的使用費用和高端的硬件支撐不是每一個公司能支付的起的绕娘。試想一下一年幾千萬的使用費用和動輒上千萬元的小型機作為硬件支撐脓规,這是一般公司能支付的起的嗎?即使就是能支付的起险领,假如有更好的方案侨舆,有更廉價且水平擴展性能更好的方案,我們?yōu)槭裁床贿x擇呢绢陌?

我們知道每臺機器無論配置多么好它都有自身的物理上限挨下,所以

當我們應用已經能觸及或遠遠超出單臺機器的某個上限的時候,我們惟有尋找別的機器的幫助或者繼續(xù)升級的我們的硬件脐湾,但常見的方案還是橫向擴展臭笆,通過添加更多的機器來共同承擔壓力

。我們還得考慮當我們的業(yè)務邏輯不斷增長秤掌,我們的機器能不能通過線性增長就能滿足需求愁铺?Sharding可以輕松的將計算,存儲闻鉴,I/O并行分發(fā)到多臺機器上帜讲,這樣可以充分利用多臺機器各種處理能力,同時可以避免單點失敗椒拗,提供系統(tǒng)的可用性似将,進行很好的錯誤隔離。

綜合以上因素蚀苛,數據切分是很有必要的在验。 我們用免費的MySQL和廉價的Server甚至是PC做集群,達到小型機+大型商業(yè)DB的效果堵未,減少大量的資金投入腋舌,降低運營成本,何樂而不為呢渗蟹?所以块饺,我們選擇Sharding赞辩,擁抱Sharding。

怎么做到數據切分

數據切分可以是物理上的授艰,對數據通過一系列的切分規(guī)則將數據分布到不同的DB服務器上辨嗽,通過路由規(guī)則路由訪問特定的數據庫,這樣一來每次訪問面對的就不是單臺服務器了淮腾,而是N臺服務器糟需,這樣就可以降低單臺機器的負載壓力。

數據切分也可以是數據庫內的谷朝,對數據通過一系列的切分規(guī)則洲押,將數據分布到一個數據庫的不同表中,比如將article分為article_001圆凰,article_002等子表杈帐,若干個子表水平拼合有組成了邏輯上一個完整的article表,這樣做的目的其實也是很簡單的专钉。舉個例子說明挑童,比如article表中現(xiàn)在有5000w條數據,此時我們需要在這個表中增加(insert)一條新的數據驶沼,insert完畢后炮沐,數據庫會針對這張表重新建立索引,5000w行數據建立索引的系統(tǒng)開銷還是不容忽視的回怜。但是反過來大年,假如我們將這個表分成100 個table呢,從article_001一直到article_100玉雾,5000w行數據平均下來翔试,每個子表里邊就只有50萬行數據,這時候我們向一張 只有50w行數據的table中insert數據后建立索引的時間就會呈數量級的下降复旬,極大了提高了DB的運行時效率垦缅,提高了DB的并發(fā)量。當然分表的好處還不知這些驹碍,還有諸如寫操作的鎖操作等壁涎,都會帶來很多顯然的好處。

綜上志秃,

分庫降低了單點機器的負載怔球;分表,提高了數據操作的效率

浮还,尤其是Write操作的效率竟坛。行文至此我們依然沒有涉及到如何切分的問題。接下來,我們將對切分規(guī)則進行詳盡的闡述和說明担汤。

上文中提到涎跨,要想做到數據的水平切分,在每一個表中都要有相冗余字符作為切分依據和標記字段崭歧,通常的應用中我們選用user_id作為區(qū)分字段隅很,基于此就有如下三種分庫的方式和規(guī)則:(當然還可以有其他的方式)

(1)

號段分區(qū)

user_id為1~1000的對應DB1,1001~2000的對應DB2驾荣,以此類推外构;

優(yōu)點:可部分遷移

缺點:數據分布不均

(2)hash取模分區(qū)

對user_id進行hash(或者如果user_id是數值型的話直接使用user_id 的值也可)普泡,然后用一個特定的數字播掷,比如應用中需要將一個數據庫切分成4個數據庫的話,我們就用4這個數字對user_id的hash值進行取模運算撼班,也就是user_id%4,這樣的話每次運算就有四種可能:結果為1的時候對應DB1歧匈;結果為2的時候對應DB2;結果為3的時候對應DB3砰嘁;結果為0的時候對應DB4件炉。這樣一來就非常均勻的將數據分配到4個DB中。

優(yōu)點:數據分布均勻

缺點:數據遷移的時候麻煩矮湘,不能按照機器性能分攤數據

(3)在認證庫中保存數據庫配置

就是建立一個DB斟冕,這個DB單獨保存user_id到DB的映射關系,每次訪問數據庫的時候都要先查詢一次這個數據庫缅阳,以得到具體的DB信息磕蛇,然后才能進行我們需要的查詢操作。

優(yōu)點:靈活性強十办,一對一關系

缺點:每次查詢之前都要多一次查詢秀撇,性能大打折扣

以上就是通常的開發(fā)中我們選擇的三種方式,有些復雜的項目中可能會混合使用這三種方式向族。 通過上面的描述呵燕,我們對分庫的規(guī)則也有了簡單的認識和了解。當然還會有更好更完善的分庫方式件相,還需要我們不斷的探索和發(fā)現(xiàn)再扭。

第3章 本課題研究的基本輪廓

分布式數據方案提供功能如下:

(1)提供分庫規(guī)則和路由規(guī)則(RouteRule簡稱RR);

(2)引入集群(Group)的概念夜矗,保證數據的高可用性泛范;

(3)引入負載均衡策略(LoadBalancePolicy簡稱LB);

(4)引入集群節(jié)點可用性探測機制侯养,對單點機器的可用性進行定時的偵測敦跌,以保證LB策略的正確實施,以確保系統(tǒng)的高度穩(wěn)定性;

(5)引入讀/寫分離柠傍,提高數據的查詢速度麸俘;

僅僅是

分庫分表

的數據層設計也是不夠完善的,當我們采用了數據庫切分方案惧笛,也就是說有N臺機器組成了一個完整的DB 从媚。如果有一臺機器宕機的話,也僅僅是一個DB的N分之一的數據不能訪問而已患整,這是我們能接受的拜效,起碼比切分之前的情況好很多了,總不至于整個DB都不能訪問各谚。

一般的應用中紧憾,這樣的機器故障導致的數據無法訪問是可以接受的,假設我們的系統(tǒng)是一個高并發(fā)的電子商務網站呢昌渤?單節(jié)點機器宕機帶來的經濟損失是非常嚴重的赴穗。也就是說,現(xiàn)在我們這樣的方案還是存在問題的膀息,容錯性能是經不起考驗的般眉。當然了,問題總是有解決方案的潜支。我們引入

集群

的概念甸赃,在此我稱之為Group,

也就是每一個分庫的節(jié)點我們引入多臺機器冗酿,每臺機器保存的數據是一樣的埠对,一般情況下這多臺機器分攤負載,當出現(xiàn)宕機情況已烤,負載均衡器將分配負載給這臺宕機的機器鸠窗。

這樣一來,就解決了容錯性的問題胯究。

[圖片上傳中...(image-2e6f15-1510072158142-0)]

如上圖所示稍计,整個數據層有Group1,Group2裕循,Group3三個集群組成臣嚣,這三個集群就是數據水平切分的結果,當然這三個集群也就組成了一個包含完整數據的DB剥哑。每一個Group包括1個Master(當然Master也可以是多個)和 N個Slave硅则,這些Master和Slave的數據是一致的。 比如Group1中的一個slave發(fā)生了宕機現(xiàn)象株婴,那么還有兩個slave是可以用的怎虫,這樣的模型總是不會造成某部分數據不能訪問的問題暑认,除非整個 Group里的機器全部宕掉,但是考慮到這樣的事情發(fā)生的概率非常写笊蟆(除非是斷電了蘸际,否則不易發(fā)生吧)。

在沒有引入集群以前徒扶,我們的一次查詢的過程大致如下:請求數據層粮彤,并傳遞必要的分庫區(qū)分字段 (通常情況下是user_id)。數據層根據區(qū)分字段Route到具體的DB姜骡,在這個確定的DB內進行數據操作导坟。

這是沒有引入集群的情況,當時引入集群會 是什么樣子的呢圈澈?我們的路由器上規(guī)則和策略其實只能路由到具體的Group惫周,也就是只能路由到一個虛擬的Group,這個Group并不是某個特定的物理服務器士败。接下來需要做的工作就是找到具體的物理的DB服務器闯两,以進行具體的數據操作褥伴。

基于這個環(huán)節(jié)的需求谅将,我們引入了

負載均衡器

的概念 (LB),負載均衡器的職責就是定位到一臺具體的DB服務器重慢。具體的規(guī)則如下:負載均衡器會分析當前sql的讀寫特性饥臂,

如果是寫操作或者是要求實時性很強的操作的話,直接將查詢負載分到Master似踱,如果是讀操作則通過負載均衡策略分配一個Slave隅熙。

我們的負載均衡器的主要研究方向也就是負載分發(fā)策略,通常情況下負載均衡包括隨機負載均衡和加權負載均衡核芽。隨機負載均衡很好理解囚戚,就是從N個Slave中隨機選取一個Slave。這樣的隨機負載均衡是不考慮機器性能的轧简,它默認為每臺機器的性能是一樣的驰坊。假如真實的情況是這樣的,這樣做也是無可厚非的哮独。假如實際情況并非如此呢拳芙?每個Slave的機器物理性能和配置不一樣的情況,再使用隨機的不考慮性能的負載均衡皮璧,是非常不科學的舟扎,這樣一來會給機器性能差的機器帶來不必要的高負載,甚至帶來宕機的危險悴务,同時高性能的數據庫服務器也不能充分發(fā)揮其物理性能睹限。基于此考慮從,我們引入了加權負載均衡羡疗,也就是在我們的系統(tǒng)內部通過一定的接口删窒,可以給每臺DB服務器分配一個權值,然后再運行時LB根據權值在集群中的比重顺囊,分配一定比例的負載給該DB服務器肌索。當然這樣的概念的引入,無疑增大了系統(tǒng)的復雜性和可維護性特碳。有得必有失消恍,我們也沒有辦法逃過的。

有了分庫乡翅,有了集群滋迈,有了負載均衡器,是不是就萬事大吉了呢益愈? 事情遠沒有我們想象的那么簡單梢灭。雖然有了這些東西,基本上能保證我們的數據層可以承受很大的壓力蒸其,但是這樣的設計并不能完全規(guī)避數據庫宕機的危害敏释。假如Group1中的slave2 宕機了,那么系統(tǒng)的LB并不能得知摸袁,這樣的話其實是很危險的钥顽,因為LB不知道,它還會以為slave2為可用狀態(tài)靠汁,所以還是會給slave2分配負載蜂大。這樣一來,問題就出來了蝶怔,客戶端很自然的就會發(fā)生數據操作失敗的錯誤或者異常奶浦。

這樣是非常不友好的!怎樣解決這樣的問題呢踢星? 我們引入集群節(jié)點的 可用性探測機制

澳叉,或者是可用性的數據推送機制。這兩種機制有什么不同呢斩狱?首先說探測機制吧耳高,顧名思義,探測即使所踊,就是我的數據層客戶端泌枪,不定時對集群中各個數據庫進行可用性的嘗試,實現(xiàn)原理就是嘗試性鏈接秕岛,或者數據庫端口的嘗試性訪問碌燕,都可以做到误证。

那數據推送機制又是什么呢?其實這個就要放在現(xiàn)實的應用場景中來討論這個問題了修壕,一般情況下應用的DB 數據庫宕機的話我相信DBA肯定是知道的愈捅,這個時候DBA手動的將數據庫的當前狀態(tài)通過程序的方式推送到客戶端,也就是分布式數據層的應用端慈鸠,這個時候在更新一個本地的DB狀態(tài)的列表蓝谨。并告知LB,這個數據庫節(jié)點不能使用青团,請不要給它分配負載譬巫。一個是主動的監(jiān)聽機制,一個是被動的被告知的機制督笆。兩者各有所長芦昔。但是都可以達到同樣的效果。這樣一來剛才假設的問題就不會發(fā)生了娃肿,即使就是發(fā)生了咕缎,那么發(fā)生的概率也會降到最低。

上面的文字中提到的Master和Slave 料扰,我們并沒有做太多深入的講解凭豪。一個Group由1個Master和N個Slave組成。為什么這么做呢记罚?其中Master負責寫操作的負載墅诡,

也就是說一切寫的操作都在Master上進行,而讀的操作則分攤到Slave上進行桐智。

這樣一來的可以大大提高讀取的效率。在一般的互聯(lián)網應用中烟馅,經過一些數據調查得出結論说庭,讀/寫的比例大概在 10:1左右 ,也就是說大量的數據操作是集中在讀的操作郑趁,這也就是為什么我們會有多個Slave的原因刊驴。

但是為什么要分離讀和寫呢?熟悉DB的研發(fā)人員都知道寡润,寫操作涉及到鎖的問題捆憎,不管是行鎖還是表鎖還是塊鎖,都是比較降低系統(tǒng)執(zhí)行效率的事情梭纹。我們這樣的分離是把寫操作集中在一個節(jié)點上躲惰,而讀操作其其他 的N個節(jié)點上進行,從另一個方面有效的提高了讀的效率变抽,保證了系統(tǒng)的高可用性础拨。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末氮块,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子诡宗,更是在濱河造成了極大的恐慌滔蝉,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件塔沃,死亡現(xiàn)場離奇詭異蝠引,居然都是意外死亡,警方通過查閱死者的電腦和手機蛀柴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門立肘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人名扛,你說我怎么就攤上這事谅年。” “怎么了肮韧?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵融蹂,是天一觀的道長。 經常有香客問我弄企,道長超燃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任拘领,我火速辦了婚禮意乓,結果婚禮上,老公的妹妹穿的比我還像新娘约素。我一直安慰自己届良,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布圣猎。 她就那樣靜靜地躺著士葫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪送悔。 梳的紋絲不亂的頭發(fā)上慢显,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音欠啤,去河邊找鬼荚藻。 笑死,一個胖子當著我的面吹牛洁段,可吹牛的內容都是我干的应狱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼眉撵,長吁一口氣:“原來是場噩夢啊……” “哼侦香!你這毒婦竟也來了落塑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤罐韩,失蹤者是張志新(化名)和其女友劉穎憾赁,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體散吵,經...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡龙考,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了矾睦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晦款。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖枚冗,靈堂內的尸體忽然破棺而出缓溅,到底是詐尸還是另有隱情,我是刑警寧澤赁温,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布坛怪,位于F島的核電站,受9級特大地震影響股囊,放射性物質發(fā)生泄漏袜匿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一稚疹、第九天 我趴在偏房一處隱蔽的房頂上張望居灯。 院中可真熱鬧,春花似錦内狗、人聲如沸怪嫌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喇勋。三九已至,卻和暖如春偎行,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贰拿。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工蛤袒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膨更。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓妙真,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荚守。 傳聞我的和親對象是個殘疾皇子珍德,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內容

  • 需要原文的可以留下郵箱我給你發(fā)练般,這里的文章少了很多圖,懶得網上粘啦 1數據庫基礎 1.1數據庫定義 1)數據庫(D...
    極簡純粹_閱讀 7,421評論 0 46
  • 原文出處: 楊步濤的博客 一锈候、 設計理念 1. 空間換時間1) 多級緩存薄料,靜態(tài)化客戶端頁面緩存(http head...
    CookieziSui閱讀 2,508評論 0 48
  • 問題導讀: 1.如何構建高并發(fā)電商平臺架構 2.哈希、B樹泵琳、倒排摄职、bitmap的作用是什么? 3.作為軟件工程師获列,...
    MaLiang閱讀 5,120評論 1 70
  • 高并發(fā)平臺架構 設計理念 1. 空間換時間 多級緩存谷市,靜態(tài)化前端頁面緩存(HTTP Header中包含Expire...
    AkaTBS閱讀 3,017評論 0 13
  • 據說有一種草迫悠,叫做“笑矣乎”。人若嗅一下巩梢,便會開心的笑起來创泄。 若植入房中,便可忘憂且改、合歡验烧。 “杜康能散悶,萱草解忘...
    小煥熊閱讀 2,269評論 0 2