
1. 前言
相信你經(jīng)常被 讀寫分離、垂直拆分、水平拆分、分庫分表 這幾個名詞搞得很懵逼。我有時候也很懵逼,那么今天就來把這幾個數(shù)據(jù)庫常用術(shù)語搞清楚,同時也記錄一下。
2. 讀寫分離
這個相對比較好理解一些,就是將數(shù)據(jù)庫分為主從庫,一個主庫(Master)用于寫數(shù)據(jù),多個從庫(Slaver)進(jìn)行輪詢讀取數(shù)據(jù)的過程,主從庫之間通過某種通訊機(jī)制進(jìn)行數(shù)據(jù)的同步,是一種常見的數(shù)據(jù)庫架構(gòu)。下面這張圖就展示了 “一主二從” 的結(jié)構(gòu):

2.1 為什么要讀寫分離
大多數(shù)互聯(lián)網(wǎng)數(shù)據(jù)操作往往都是讀多寫少,隨著數(shù)據(jù)的增長,數(shù)據(jù)庫的“讀”會首先成為瓶頸。如果我們希望能線性地提升數(shù)據(jù)庫的讀性能和寫性能,就需要讓讀寫盡可能的不相互影響,各自為政。在使用讀寫分離之前我們應(yīng)該考慮使用緩存能不能解決問題。然后再考慮對數(shù)據(jù)庫按照 “讀” 和 “寫” 進(jìn)行分組。讀寫分離意味著將一體的結(jié)構(gòu)的進(jìn)行分散,在數(shù)據(jù)量大、高并發(fā)的情景中要考慮以下這些問題
- 如何保證 Master 的高可用,故障轉(zhuǎn)移,熔斷限流等。
- 讀寫操作的區(qū)分規(guī)則,代碼層面如何處理好讀命令和寫命令,盡量無感知無業(yè)務(wù)入侵。
- 數(shù)據(jù)一致性的容忍度。雖然是數(shù)據(jù)同步,但是由于網(wǎng)絡(luò)的不確定性這仍然是一個不可忽視的問題。
3. 分庫
數(shù)據(jù)庫垂直拆分、數(shù)據(jù)庫水平拆分 統(tǒng)稱 分庫。是指按照特定的條條件和維度,將同一個數(shù)據(jù)庫中的數(shù)據(jù)拆分到多個數(shù)據(jù)庫(主機(jī))上面以達(dá)到分散單庫(主機(jī))負(fù)載的效果。這樣我們變相地降低了數(shù)據(jù)集的大小,以空間換時間來提升性能。
3.1 數(shù)據(jù)庫垂直拆分
數(shù)據(jù)庫垂直拆分 指的是按照業(yè)務(wù)對數(shù)據(jù)庫中的表進(jìn)行分組,同組的放到一個新的數(shù)據(jù)庫(邏輯上,并非實(shí)例)中。需要從實(shí)際業(yè)務(wù)出發(fā)將大業(yè)務(wù)分割成小業(yè)務(wù)。比如商城的整個業(yè)務(wù)中的 用戶相關(guān)表,訂單相關(guān)表,物流相關(guān)表 各自獨(dú)立分類形成 用戶系統(tǒng)數(shù)據(jù)庫,訂單系統(tǒng)數(shù)據(jù)庫,物流系統(tǒng)數(shù)據(jù)庫 如下圖:

這樣帶來了一些好處: (a)業(yè)務(wù)清晰,職責(zé)單一 (b)易維護(hù),易擴(kuò)展 (c)數(shù)據(jù)服務(wù)化 。 同時也有一些負(fù)面的作用:(a)提高了整個應(yīng)用的復(fù)雜度,而且會形成跨庫事務(wù) (b)引發(fā) “木桶效應(yīng)”,任何一個短板有可能影響整個系統(tǒng) (c)部分表關(guān)系不能 join 只能通過服務(wù)相互調(diào)用來維系。甚至由于網(wǎng)絡(luò)問題引發(fā)數(shù)據(jù)不一致。
在需要進(jìn)行分庫的情況下,通??蓛?yōu)先考慮垂直拆分。
3.2 數(shù)據(jù)庫水平拆分
在數(shù)據(jù)庫垂直拆分后遇到單機(jī)數(shù)據(jù)庫性能瓶頸之后,就可以考慮數(shù)據(jù)庫水平拆分了。 之所以先垂直拆分才水平拆分,是因?yàn)榇怪辈鸱趾髷?shù)據(jù)業(yè)務(wù)清晰而且單一,更加方便指定水平的標(biāo)準(zhǔn)。比如我們對商城業(yè)務(wù)垂直拆分后的 用戶系統(tǒng) 進(jìn)行水平拆分就比對整個商城業(yè)務(wù)進(jìn)行水平拆分好找維度,我們可以根據(jù)用戶注冊時間的區(qū)間、用戶的區(qū)域或者用戶 ID 的范圍、 hash 等條件,然后關(guān)聯(lián)相關(guān)表的記錄將數(shù)據(jù)進(jìn)行拆分,如果放在整個商城業(yè)務(wù)上你是以用戶為準(zhǔn)還是以訂單為準(zhǔn)都不太好考慮。
我們按照每100萬為區(qū)間對用戶系統(tǒng)水平拆分如下:

這種拆分的好處在于: (a)單個庫的容量可控 (b)單挑記錄保證了數(shù)據(jù)完整性 (c)數(shù)據(jù)關(guān)系可以通過 join 維持 (d) 避免了跨庫事務(wù) ;缺點(diǎn)同樣存在:(a)拆分規(guī)則對編碼有一定的影響 (b)不同業(yè)務(wù)的分區(qū)交互需要統(tǒng)籌設(shè)計
4. 分表
分表也分為 數(shù)據(jù)表垂直拆分 和 數(shù)據(jù)表水平拆分 。
4.1 數(shù)據(jù)表垂直拆分
數(shù)據(jù)表垂直拆分就是縱向地把表中的列分成多個表,把表從“寬”變“窄”。一般遵循以下幾個點(diǎn)進(jìn)行拆分:
- 冷熱分離,把常用的列放在一個表,不常用的放在一個表。
- 大字段列獨(dú)立存放
- 關(guān)聯(lián)關(guān)系的列緊密的放在一起
我們把用戶表中常用的和不常用的而且大字段分離成兩張表:

4.2 數(shù)據(jù)表的水平拆分
表的水平拆分感覺跟庫的水平拆分思想上都是一樣的,只不過粒度不同。表結(jié)構(gòu)維持不變。也就是說拆分后數(shù)據(jù)集的并集等于拆分前的數(shù)據(jù)集。理解了 3.2 章節(jié) 之后這個就沒有什么可說的了。
5. 總結(jié)
這里簡單闡述了幾個數(shù)據(jù)庫優(yōu)化概念,在實(shí)際操作中往往會組合使用。我們在實(shí)際操作之前要做好數(shù)據(jù)量的預(yù)估,這樣能夠根據(jù)預(yù)測未來數(shù)據(jù)的增量來進(jìn)行選型。業(yè)務(wù)數(shù)據(jù)增長較小,常用于表的拆分。增長特別大達(dá)到上萬級別則可以選擇分庫,比如一些資金積分流水,歷史記錄之類的。有些時候并不是拆分完就萬事大吉了,比如我們按照地區(qū)拆分后,A地區(qū)業(yè)務(wù)增長很快業(yè)績很好,而B地區(qū)推廣不力競爭激烈業(yè)績蕭條,造成了數(shù)據(jù)傾斜。也會影響分庫分表的期望效果。這需要建立長效的監(jiān)控預(yù)測機(jī)制來應(yīng)對,甚至根據(jù)實(shí)際情況及時調(diào)整策略。數(shù)據(jù)拆分還面臨分布式的很多問題,分布式事務(wù),高可用,數(shù)據(jù)一致性,全局唯一性都是應(yīng)該考慮的問題。如果你有什么問題可以通過公眾號:Felordcn 與我交流。
關(guān)注公眾號:碼農(nóng)小胖哥,獲取更多資訊