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