access 分表存储_sharding:谁都能读懂的分库、分表、分区
本文通過大量圖片來分析和描述分庫、分表以及數(shù)據(jù)庫分區(qū)是怎樣進(jìn)行的。
1.sharding前的初始數(shù)據(jù)分布
在本文中,我打算用高考考生相關(guān)信息作為實(shí)驗(yàn)數(shù)據(jù)。請(qǐng)無視表的字段是否符合現(xiàn)實(shí),也請(qǐng)無視表的設(shè)計(jì)是否符合范式。
3張表:
考生表,存放全國所有高考考生信息,假設(shè)34個(gè)省、(直轄)市、(自治區(qū)、特別行政)區(qū)共3000W考生
學(xué)科表,分文理科,共9門課程(語文、數(shù)學(xué)、英語、歷史、地理、政治、物理、化學(xué)、生物)
成績表,存過全國所有考生所有學(xué)科成績,每個(gè)學(xué)生6門成績,共1.8億條成績數(shù)據(jù)
三張表放在名為"gaokao_db"的庫中。所以,它們的結(jié)構(gòu)如下:
這三張表的大致存儲(chǔ)方式如下:
這個(gè)時(shí)候數(shù)據(jù)存儲(chǔ)方式是單庫多表。
2.業(yè)務(wù)分庫
業(yè)務(wù)分庫:按業(yè)務(wù)將不同表放進(jìn)不同庫。每個(gè)庫可以放在不同數(shù)據(jù)庫服務(wù)器上。
例如,在這里將原始數(shù)據(jù)庫gaokao_db中的3個(gè)表分開放進(jìn)兩個(gè)數(shù)據(jù)庫中,stu_db存放考生表,score_db存放成績表。
還有一張學(xué)科表放在哪呢?對(duì)于那些很小、無需進(jìn)行切片的表,可以將多個(gè)這樣的表共同放在同一個(gè)庫中,也可以根據(jù)聯(lián)接特性將其分開放置在常與之進(jìn)行聯(lián)接的庫中。在此處,學(xué)科表很小,沒必要單獨(dú)占用一個(gè)庫甚至數(shù)據(jù)庫服務(wù)器,且由于學(xué)科表只會(huì)和成績表進(jìn)行聯(lián)接,所以將其放在score_db庫中。
業(yè)務(wù)分庫如下圖:
stu_db和score_db可以放在同一數(shù)據(jù)庫服務(wù)器上,也可以放在不同數(shù)據(jù)庫服務(wù)器上,從而在整體上減輕系統(tǒng)的壓力。但是,如果這兩個(gè)庫放在不同服務(wù)器上,因?yàn)榭鐢?shù)據(jù)庫實(shí)例,將沒法對(duì)stu_db和score_db中的表進(jìn)行join操作。
一般來說,對(duì)于可預(yù)見的、不斷增長的數(shù)據(jù),業(yè)務(wù)分庫可能最先進(jìn)行的sharding。
3.垂直切分
垂直切分:將一個(gè)表按照字段分成多表,每個(gè)表存儲(chǔ)一部分字段。表可以放在不同存儲(chǔ)設(shè)備上。
其實(shí),在最初設(shè)計(jì)數(shù)據(jù)庫的時(shí)候,因?yàn)槭顷P(guān)系型數(shù)據(jù)庫,或多或少都會(huì)去遵守一些設(shè)計(jì)范式。當(dāng)設(shè)計(jì)的數(shù)據(jù)庫表滿足第一范式、第二范式、第三范式等等范式要求時(shí),其實(shí)就已經(jīng)進(jìn)行了所謂的垂直切分。
即使按照范式設(shè)計(jì)了數(shù)據(jù)庫表,但有些表是寬表,有很多可能很少使用的字段,這些字段可能是按照稀疏列進(jìn)行管理的,也可能是大BLOB后大text字段。此外,表中的字段還可以劃分為"熱門字段和冷門字段",例如本文示例中,相比考生號(hào)、姓名、所屬地區(qū)使用頻繁程度,考生電話號(hào)碼可能很少使用、身份證號(hào)也很少使用,所以這兩個(gè)字段是冷門字段。
所以,當(dāng)表數(shù)據(jù)量很大時(shí),即使?jié)M足了范式要求,還是可以強(qiáng)行將表按字段切開,將熱門字段、冷門字段分開放置在不同庫中,這些庫可以放在不同的存儲(chǔ)設(shè)備上,避免IO爭搶。
如下圖:
注意,垂直切分后的表,要能進(jìn)行關(guān)聯(lián),所以在此處的其它信息表中加上了考生號(hào)字段。
垂直切分其實(shí)是更深一步的范式設(shè)計(jì),或者反范式設(shè)計(jì)。垂直切分帶來的性能提升,主要集中在熱門數(shù)據(jù)的操作效率上,而且磁盤爭用情況減少。但如果想要將兩個(gè)表中的數(shù)據(jù)再次聯(lián)合起來,性能將比垂直切分前差的多。
另外,有很多人將業(yè)務(wù)分庫當(dāng)作垂直切分,其實(shí)這都不重要,重要的是知道各種手段是干嘛的。不過在本文以及我后面的文章,將認(rèn)為業(yè)務(wù)分庫和垂直切分是不同sharding的分類。
4.水平切分
水平切分:將大表按條件切分到不同表中。每個(gè)表存儲(chǔ)一部分滿足條件的行。
水平切分通常有幾種常用的切分方式:
直接按字段條件切分
取模后切分
按月份、季度、年份切分,或者稱之為按范圍切分
水平切分對(duì)性能提升非常大,不僅可以避開服務(wù)器資源爭用,還減小了索引大小以及每個(gè)庫維護(hù)的表數(shù)據(jù)量。
4.1 按字段條件進(jìn)行切分
例如本文的示例中,按照考生所屬地區(qū)對(duì)考生表進(jìn)行水平切分,這是按照字段條件進(jìn)行切分。
如下圖,因?yàn)橛?4個(gè)省、市、區(qū),所以分成34個(gè)考生表,每個(gè)考生表都放在地區(qū)命名的庫中。各庫可放在同一數(shù)據(jù)庫服務(wù)器,也可以放在不同數(shù)據(jù)庫服務(wù)器。例如,某些省市區(qū)的考生數(shù)量少,可以將多個(gè)這樣的庫放在同一個(gè)數(shù)據(jù)庫服務(wù)器上,而山東、江西等高考大省,因?yàn)榭忌鷶?shù)量多,可以單獨(dú)放在同一個(gè)數(shù)據(jù)庫服務(wù)器上。
注意上述按字段條件進(jìn)行水平切分時(shí),表名不變,創(chuàng)建新的按地區(qū)命名的庫,將各地區(qū)的表放置在對(duì)應(yīng)的庫中。
通常,按照字段條件進(jìn)行水平切分時(shí),其它表也很有可能也按這個(gè)條件進(jìn)行切分,使得滿足條件的表都放在同一個(gè)庫中,這樣能保證正常的join操作。
例如,上面切分了考生表,還可以切分成績表,讓同一個(gè)地區(qū)的考生表、成績表放在同一個(gè)庫中(所以,不能將考生表、成績表進(jìn)行業(yè)務(wù)分庫)。
這樣切分后,整個(gè)數(shù)據(jù)的分布情況如下:
4.2 按范圍進(jìn)行切分
對(duì)于上面的成績表,如果在此之前已經(jīng)進(jìn)行了業(yè)務(wù)分庫,就無法讓成績表、考生表同時(shí)按照地區(qū)進(jìn)行水平切分。這時(shí)可以進(jìn)行范圍切分,最常見的范圍切分是按月份、季度、年份進(jìn)行切分。
例如,本文示例的成績表,可以按考生號(hào)范圍切片,可按考生號(hào)取模后切片,也可按學(xué)科類別切片。例如,按考生號(hào)范圍切片,每張表500W考生共3000W條成績數(shù)據(jù),共切成6片。
注意按照范圍(或者取模、年份、月份、季度等)切片后,數(shù)據(jù)庫的命名。這些庫可以放在同一個(gè)數(shù)據(jù)庫服務(wù)器上,也可以放在不同數(shù)據(jù)庫服務(wù)器上。
如果對(duì)成績表按照范圍(或者取模、年份、月份、季度等)切片后,最好對(duì)考生表也按照同樣的切分方式進(jìn)行切片。舉個(gè)反例很容易理解,這里的成績表按照范圍切分了,但是考生表按照地區(qū)切分,這兩類庫的名稱之間將失去對(duì)應(yīng)關(guān)系,對(duì)于數(shù)據(jù)維護(hù)來說可能會(huì)增加很大的難度。
按照這種模式的水平切分后,整個(gè)數(shù)據(jù)的分布情況如下(假設(shè)考生表也按范圍切片):
4.3 取模切分
取模是對(duì)數(shù)值或能轉(zhuǎn)換為數(shù)值的字段進(jìn)行取模,要切分成幾片,就除幾。
例如,按照取模切分的方式,將本文的考生表切分成6片。于是:
00000001 % 6 = 1 --> 放進(jìn)stu_1庫
00000002 % 6 = 2 --> 放進(jìn)stu_2庫
00000003 % 6 = 3 --> 放進(jìn)stu_3庫
00000004 % 6 = 4 --> 放進(jìn)stu_4庫
00000005 % 6 = 5 --> 放進(jìn)stu_5庫
00000006 % 6 = 0 --> 放進(jìn)stu_0庫
...
00000101 % 6 = 5 --> 放進(jìn)stu_5庫
00000102 % 6 = 0 --> 放進(jìn)stu_0庫
00000103 % 6 = 1 --> 放進(jìn)stu_1庫
00000104 % 6 = 2 --> 放進(jìn)stu_2庫
00000105 % 6 = 3 --> 放進(jìn)stu_3庫
00000106 % 6 = 4 --> 放進(jìn)stu_4庫
...
注意,取模切片后的表名仍然為考生表,這些考生表放在對(duì)應(yīng)的庫里,這些庫可以單獨(dú)放在一個(gè)數(shù)據(jù)庫服務(wù)器上,也可以多個(gè)庫一起放在同一個(gè)數(shù)據(jù)庫服務(wù)器上。
5.數(shù)據(jù)庫分區(qū)
數(shù)據(jù)庫分區(qū):將大表進(jìn)行分區(qū),不同分區(qū)可以放置在不同存儲(chǔ)設(shè)備上,這些分區(qū)在邏輯上組成一個(gè)大表,對(duì)客戶端透明
分區(qū)方式和水平切片是類似的,分區(qū)方式也和水平切片方式類似,如范圍切片,取模切片等
數(shù)據(jù)庫分區(qū)是數(shù)據(jù)庫自身的特性,切片則是外部強(qiáng)制手段控制完成的
數(shù)據(jù)庫分區(qū)無法將分區(qū)跨庫,更不能跨數(shù)據(jù)庫服務(wù)器,但能保存在不同數(shù)據(jù)文件從而放置在不同存儲(chǔ)設(shè)備上
數(shù)據(jù)庫分區(qū)是數(shù)據(jù)庫的特性,數(shù)據(jù)完整性、一致性等實(shí)現(xiàn)起來很方便,這一切都是數(shù)據(jù)庫自身保證的
例如,對(duì)考生表按照地區(qū)進(jìn)行分區(qū)。
在數(shù)據(jù)庫切片流行之前,對(duì)大表的處理方式就是劃分分區(qū)表。數(shù)據(jù)庫分區(qū)相比于切片,最大的缺點(diǎn)在于無法跨庫、跨服務(wù)器,所以在某些方面的壓力得到不緩解。
6.分庫、分表帶來的問題
因?yàn)榉謳臁⒎直砜梢詫⒋蟊砬蟹殖啥鄠€(gè)片段,每次檢索時(shí)可以只檢索一小個(gè)片段,且因?yàn)檫@些片段可以分開存放在不同存儲(chǔ)設(shè)備、不同數(shù)據(jù)庫服務(wù)器上,它的整體性能得到了很大的提高。但是,隨之而來不少問題。最主要集中在以下幾個(gè)方面。
1.分庫分表本身的復(fù)雜性
分庫分表的方式可以在開發(fā)端通過代碼來實(shí)現(xiàn),也可以在app和數(shù)據(jù)庫中間使用中間件來實(shí)現(xiàn)(如mycat),還可以直接使用分布式數(shù)據(jù)庫(如TiDB、OceanBase)替代傳統(tǒng)關(guān)系型數(shù)據(jù)庫。無論是哪一種方案,學(xué)習(xí)成本、維護(hù)成本都有一段陣痛時(shí)期。
2.分庫分表讓數(shù)據(jù)庫系統(tǒng)架構(gòu)變得復(fù)雜
特別是添加中間件的方式,畢竟在app和數(shù)據(jù)庫中間多了一層,這一層不能出現(xiàn)單點(diǎn)故障。
3.跨節(jié)點(diǎn)join問題
當(dāng)進(jìn)行了業(yè)務(wù)分庫,或者其它切片方式將庫放置在不同數(shù)據(jù)庫實(shí)例上時(shí),因?yàn)榭缌藢?shí)例,將無法進(jìn)行join操作。
4.擴(kuò)容和數(shù)據(jù)遷移艱難
對(duì)于那些以范圍、取模方式做水平切分的大表,擴(kuò)容以及擴(kuò)容時(shí)的數(shù)據(jù)遷移很艱難。需要解決幾個(gè)問題:
擴(kuò)容到多少節(jié)點(diǎn)比較滿足自己的期望。
擴(kuò)容時(shí),哪些數(shù)據(jù)需要從舊節(jié)點(diǎn)清洗掉,哪些數(shù)據(jù)需要從舊節(jié)點(diǎn)遷移到新節(jié)點(diǎn)。
如何實(shí)現(xiàn)在線遷移。
例如原本按照4個(gè)節(jié)點(diǎn)取模分片,現(xiàn)在出現(xiàn)了瓶頸,想要擴(kuò)容成6個(gè)節(jié)點(diǎn)。
第一個(gè)問題,從4個(gè)節(jié)點(diǎn)擴(kuò)容為6個(gè)節(jié)點(diǎn),在整體上大致能提升50%的性能。
第二個(gè)問題和第三個(gè)問題。看如下數(shù)據(jù)分布情況
擴(kuò)容前 擴(kuò)容后
0 % 4 = 0 0 % 6 = 0
1 % 4 = 1 1 % 6 = 1
2 % 4 = 2 2 % 6 = 2
3 % 4 = 3 3 % 6 = 3
4 % 4 = 0 4 % 6 = 4 -> 從0節(jié)點(diǎn)遷移到4節(jié)點(diǎn)
5 % 4 = 1 5 % 6 = 5 -> 從1節(jié)點(diǎn)遷移到5節(jié)點(diǎn)
6 % 4 = 2 6 % 6 = 0 -> 從2節(jié)點(diǎn)遷移到0節(jié)點(diǎn)
7 % 4 = 3 7 % 6 = 1 -> 從3節(jié)點(diǎn)遷移到1節(jié)點(diǎn)
8 % 4 = 0 8 % 6 = 2 -> 從0節(jié)點(diǎn)遷移到2節(jié)點(diǎn)
9 % 4 = 1 9 % 6 = 3 -> 從1節(jié)點(diǎn)遷移到3節(jié)點(diǎn)
10 % 4 = 2 10 % 6 = 4 -> 從2節(jié)點(diǎn)遷移到4節(jié)點(diǎn)
11 % 4 = 3 11 % 6 = 5 -> 從3節(jié)點(diǎn)遷移到5節(jié)點(diǎn)
12 % 4 = 0 12 % 6 = 0
13 % 4 = 1 13 % 6 = 1
14 % 4 = 2 14 % 6 = 2
15 % 4 = 3 15 % 6 = 3
16 % 4 = 0 16 % 6 = 4 -> 從0節(jié)點(diǎn)遷移到4節(jié)點(diǎn)
可見,每12條數(shù)據(jù)就要從舊節(jié)點(diǎn)遷移8條數(shù)據(jù),而且這8掉數(shù)據(jù)還是在各個(gè)節(jié)點(diǎn)之間交叉遷移。這使得數(shù)據(jù)遷移非常復(fù)雜,不是想加幾個(gè)節(jié)點(diǎn)就加幾個(gè)節(jié)點(diǎn),讓擴(kuò)容變得不再隨心所欲。一種比較好的解決方案是雙倍擴(kuò)容,例如從4節(jié)點(diǎn)擴(kuò)容為8節(jié)點(diǎn)。
擴(kuò)容前 擴(kuò)容后
0 % 4 = 0 0 % 8 = 0
1 % 4 = 1 1 % 8 = 1
2 % 4 = 2 2 % 8 = 2
3 % 4 = 3 3 % 8 = 3
4 % 4 = 0 4 % 8 = 4 -> 從0節(jié)點(diǎn)遷移到4節(jié)點(diǎn)
5 % 4 = 1 5 % 8 = 5 -> 從1節(jié)點(diǎn)遷移到5節(jié)點(diǎn)
6 % 4 = 2 6 % 8 = 6 -> 從2節(jié)點(diǎn)遷移到6節(jié)點(diǎn)
7 % 4 = 3 7 % 8 = 7 -> 從3節(jié)點(diǎn)遷移到7節(jié)點(diǎn)
8 % 4 = 0 8 % 8 = 0
9 % 4 = 1 9 % 8 = 1
10 % 4 = 2 10 % 8 = 2
11 % 4 = 3 11 % 8 = 3
12 % 4 = 0 12 % 8 = 4 -> 從0節(jié)點(diǎn)遷移到4節(jié)點(diǎn)
13 % 4 = 1 13 % 8 = 5 -> 從1節(jié)點(diǎn)遷移到5節(jié)點(diǎn)
14 % 4 = 2 14 % 8 = 6 -> 從2節(jié)點(diǎn)遷移到6節(jié)點(diǎn)
15 % 4 = 3 15 % 8 = 7 -> 從3節(jié)點(diǎn)遷移到7節(jié)點(diǎn)
16 % 4 = 0 16 % 8 = 0
這樣每8條數(shù)據(jù)遷移4條,且需要遷移的數(shù)據(jù)不會(huì)在各節(jié)點(diǎn)之間交叉。這樣遷移要方便的的,而且性能提升100%。但是因?yàn)橐w移的數(shù)據(jù)量較大,遷移速度較慢,而且每次擴(kuò)容都采取雙倍擴(kuò)容,必須要考慮服務(wù)器成本。
還有一種比較流行的"業(yè)務(wù)雙寫"遷移法。相比于雙倍擴(kuò)容法,它仍然很復(fù)雜。它的遷移過程大概是這樣的:
加入新節(jié)點(diǎn)。
將業(yè)務(wù)寫入過程按照舊規(guī)則和新規(guī)則同時(shí)寫到新舊節(jié)點(diǎn)(業(yè)務(wù)雙寫)。例如4節(jié)點(diǎn)擴(kuò)容到6節(jié)點(diǎn)時(shí),id=2000的數(shù)據(jù)(假設(shè)之前沒有該數(shù)據(jù))將同時(shí)寫入到0節(jié)點(diǎn)和2節(jié)點(diǎn),id=2003將同時(shí)寫入3節(jié)點(diǎn)和5節(jié)點(diǎn)。
遷移舊數(shù)據(jù)。
應(yīng)用新規(guī)則,將新節(jié)點(diǎn)向外提供服務(wù)。
清洗舊數(shù)據(jù)。
雙寫能保證遷移數(shù)據(jù)的過程仍然持續(xù)在線提供服務(wù)。但是,那些已存在的舊數(shù)據(jù)遷移仍然較為復(fù)雜,需要仔細(xì)琢磨要遷移哪些數(shù)據(jù),以及遷移到哪個(gè)節(jié)點(diǎn),這點(diǎn)必須把控好。
總結(jié)
以上是生活随笔為你收集整理的access 分表存储_sharding:谁都能读懂的分库、分表、分区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 复合油脂(复合油)
- 下一篇: python解密md5值_Python之