分庫分表實戰(zhàn):新的挑戰(zhàn)—千萬級數(shù)據(jù)優(yōu)化之垂直拆分
前 言
讀寫分離方案上線后,訂單sql查詢時間再一次穩(wěn)定在了300ms以下,此時對數(shù)據(jù)的增刪改操作會走主庫,而讀請求會走從庫,通過讀寫分離大大提升了數(shù)據(jù)讀的處理能力,但遺憾的是沒辦法提升主庫寫數(shù)據(jù)的能力。
新的挑戰(zhàn)
那么什么時候主庫寫數(shù)據(jù)的壓力會過大呢?其實我們之前也聊過這個問題,那就是多個業(yè)務(wù)共用一個物理數(shù)據(jù)庫的,比如商品相關(guān)的表、訂單相關(guān)的表和用戶相關(guān)的表等,所有表都放到了一個mysql數(shù)據(jù)庫中,就像這樣:
此時商品模塊、訂單模塊、用戶模塊都部署在同一臺物理數(shù)據(jù)庫上,說白了就是主庫上,那么此時這臺物理數(shù)據(jù)庫的CPU、內(nèi)存和網(wǎng)絡(luò)的負載能力,都是商品模塊、訂單模塊、用戶模塊共用的。
這就很尷尬了,由于這3個模塊是共用同一臺數(shù)據(jù)庫的資源,那么就勢必會相互影響,比如某一天商品模塊做了一些活動,尷尬的是商品模塊并沒有做讀寫分離,那么這個時候可能商品模塊,會對這臺物理數(shù)據(jù)庫進行大量的讀操作,此時這臺物理數(shù)據(jù)庫的CPU、內(nèi)存和網(wǎng)絡(luò)負載占用都很高。
而數(shù)據(jù)庫的資源是有限的,既然商品模塊占用了大量的數(shù)據(jù)庫資源,那么留給訂單模塊可用的資源就非常少了,這個時候就會導(dǎo)致訂單庫寫數(shù)據(jù)很慢,寫入一條訂單數(shù)據(jù)突增到了2s,對于訂單來說,這個肯定是萬萬不能接受的
那么有沒有破局之道呢?那當(dāng)然是有的,那就是垂直拆分。
怎么做垂直拆分?
垂直拆分其實分為垂直分庫和垂直分表,我們這里指的是垂直分庫,說白了就是由一個數(shù)據(jù)庫拆分出來多個數(shù)據(jù)庫,那么具體怎么拆分呢?
其實可以從數(shù)據(jù)表的維度來拆分,將表做一個分類,比如之前一個庫100張表,現(xiàn)在我分成了10個mysql數(shù)據(jù)庫,每個數(shù)據(jù)庫10張表的數(shù)據(jù),這樣每個數(shù)據(jù)庫的壓力就會很小。
垂直拆分說白了就是將一個大的系統(tǒng)的多張表,做一個分類,一般按照模塊來拆分出一個一個的數(shù)據(jù)庫,而每個數(shù)據(jù)庫中只存放一類數(shù)據(jù)表,每個數(shù)據(jù)庫都有一批表,而且都是同一個模塊的表。
比如一般在外賣系統(tǒng)中,包含商品模塊、訂單模塊、用戶模塊等,垂直拆分就是將每個模塊的一類表,都分別放到單獨的庫中,分而治之,這樣說白了就是分布式系統(tǒng)、微服務(wù)拆分后的效果了:
這樣就可以解決剛才的問題了,因為根本原因是這3個模塊共用了一臺數(shù)據(jù)庫的資源,結(jié)果商品模塊占用數(shù)據(jù)庫服務(wù)器大量資源的時候,留給訂單模塊的資源自然就少了,所以破局之道就是我們就需要把這3個模塊的數(shù)據(jù)庫拆分開,不讓它們共用一臺物理數(shù)據(jù)庫,而是給每個業(yè)務(wù)模塊,配備一臺自己獨立的物理數(shù)據(jù)庫服務(wù)器,說白了就是將數(shù)據(jù)庫進行了垂直分庫,由共用一個大雜燴數(shù)據(jù)庫,拆分為獨立的商品數(shù)據(jù)庫、訂單數(shù)據(jù)庫和用戶數(shù)據(jù)庫。
不過在實際的分庫中,我們可能需要考慮一個情況,就是有些模塊關(guān)聯(lián)性比較大,可能經(jīng)常需要一起查詢。所以這時候,我們也可以把強關(guān)聯(lián)的一些模塊的表放在一個庫,避免跨庫查詢帶來的效率降低。
好了,此時由于我們已經(jīng)把不同模塊的表放到了不同的數(shù)據(jù)庫中,每個庫都有自己獨立的一臺物理服務(wù)器,那么這臺物理數(shù)據(jù)庫的CPU、內(nèi)存和網(wǎng)絡(luò)的負載能力都是相互隔離的,因此之前資源相互占用的問題也就不存在了。
垂直拆分有哪些好處呢?
垂直拆分是可以帶來很多好處的,比如可以幫我們減輕數(shù)據(jù)庫的壓力,當(dāng)我們按照模塊分庫之后,不同模塊的數(shù)據(jù)表,現(xiàn)在已經(jīng)被分到了多個數(shù)據(jù)庫中了,每個數(shù)據(jù)庫中的數(shù)據(jù),就不會那么多了,查詢的效率就會更高了。
另外,單個數(shù)據(jù)庫的數(shù)據(jù)量變少了之后,相應(yīng)的CPU、內(nèi)存、網(wǎng)絡(luò)的負載的壓力,也會相應(yīng)的降低,整體的查詢效率也會提高。
垂直拆分后,業(yè)務(wù)會變的更加清晰,維護數(shù)據(jù)也會很方便,因為一個庫拆分成了多個庫,每個庫中的表都是一個業(yè)務(wù)模塊的,所以一個庫中就一個模塊的業(yè)務(wù),很清晰。
并且,數(shù)據(jù)維護也是,需要找哪個模塊的數(shù)據(jù),就到對應(yīng)庫中找,不會像拆分前,多個模塊的數(shù)據(jù)糅在一起,維護數(shù)據(jù)也簡單,因為多個模塊的數(shù)據(jù),解耦了,修改一個庫中的數(shù)據(jù),不會影響其他庫的數(shù)據(jù)。
而且,系統(tǒng)擴展也會變的更容易一些,現(xiàn)在各個模塊都拆分出來了,比如訂單模塊,就從外賣系統(tǒng)中,單獨拆分出來一個模塊了,這個訂單模塊的數(shù)據(jù),在一個數(shù)據(jù)庫中和其他模塊的數(shù)據(jù),就獨立了。
如果訂單模塊業(yè)務(wù)要做復(fù)雜了,需要擴展了,比如訂單的表結(jié)構(gòu)要設(shè)計的更復(fù)雜點,添加更多的業(yè)務(wù)設(shè)計,對其它模塊都是透明的,很容易擴展;不會像之前一樣,多個模塊的多張表,耦合在一個庫中,也不好拓展,因為會擔(dān)心影響到其他業(yè)務(wù)。
垂直拆分有什么不足的地方嗎?
好了,說了垂直分庫的這么多好處,那么它有沒有一些不足的地方呢?答案是肯定的。
首先就是系統(tǒng)會變的更復(fù)雜,因為現(xiàn)在垂直拆分之后,多個模塊的表,都分別分到不同的數(shù)據(jù)庫中了,如果現(xiàn)在有一個查詢操作,要關(guān)聯(lián)多張表,這個時候,就不能簡單使用join來進行關(guān)聯(lián)查詢了。
比如a表在A庫,b表在B庫,這個時候就不能簡單的join連接了,而需要先通過接口的方式,先獲取到a表的數(shù)據(jù),然后再通過接口獲取b表的數(shù)據(jù),這樣操作就變復(fù)雜了。
另外,事務(wù)的處理也會變得更加的麻煩,之前要處理事務(wù)的話,在一個數(shù)據(jù)庫中處理即可,出現(xiàn)問題直接回滾事務(wù)就行了。
但是現(xiàn)在要操作的數(shù)據(jù),可能是分布在多個數(shù)據(jù)庫中的,如果操作過程中的某個環(huán)節(jié)出問題了,就不能簡單的回滾事務(wù)了,因為現(xiàn)在是橫跨多個數(shù)據(jù)庫的事務(wù),這個時候就要用到分布式事務(wù)的解決方案了,就更復(fù)雜了。
而且,單庫的性能也會很快的遇到瓶頸,雖然現(xiàn)在一個大的系統(tǒng)的多張表,按照不同??烨谐隽硕鄠€數(shù)據(jù)庫,每個庫有相應(yīng)模塊的表,可能某一個模塊的數(shù)據(jù)量會特別大,比如訂單模塊,相比于其他模塊而言,數(shù)據(jù)量會非常大。
并且這里通常是單表數(shù)據(jù)量過大,比如訂單表單表可能已經(jīng)6000W數(shù)據(jù)了,這個時候訂單表的讀寫效率已經(jīng)開始明顯降低了。
像這種單表數(shù)據(jù)量過大的問題,垂直分庫是解決不了的,所以這個時候就需要對訂單表進行進一步的拆分,也就是水平拆分。
由于我們實戰(zhàn)是以外賣訂單業(yè)務(wù)為主,所以本身就只有一個訂單數(shù)據(jù)庫,其實天然就已經(jīng)做了垂直分庫,所以這個垂直分庫我們就不進行實戰(zhàn)了,后邊的水平分庫分表是我們的重頭戲,到時候會帶著大家一起設(shè)計水平分庫分表的落地方案和數(shù)據(jù)遷移方案的,大家敬請期待!