1. 程式人生 > >mysql分庫分表方案淺析

mysql分庫分表方案淺析

分庫分表(這裡不討論中介軟體)

分庫:原因:單機負載高,優點:降低單機負載
分表:原因:單表讀寫壓力大或者資料增長快,優點:使用多個表,提高讀寫效率
1、(程式碼)分表,即把一個很大的表達資料分到幾個表中,這樣每個表資料都不多。
                 優點:提高併發量,減小鎖的粒度
                 缺點:程式碼維護成本高,相關sql都需要改動

2、(mysql)分割槽,所有的資料還在一個表中,但物理儲存資料根據一定的規則存放在不同的檔案中,檔案也可以放到另外磁碟上
                    優點:程式碼維護量小,基本不用改動,提高IO吞吐量
                    缺點:表的併發程度沒有增加



分表
在一個庫中進行進行分表,有兩種方法
1、mysql表分割槽(推薦)
使用表分割槽時,分割槽欄位。需要根據業務來定,這裡所說的業務,指的就是需要做分表的表會和哪些業務相關,
比如訂單表,主鍵是訂單ID,分表時,需要結合業務綜合看待。
單純就技術看:
如果按訂單ID進行hash,操作分佈多個表,但是在拓展時,就很麻煩
如果按訂單ID進行範圍range,操作集中某幾個表,拓展時,很方便
綜合結合看:
a,當業務需要根據時間來查詢
如果按訂單ID進行表分割槽,那麼會造成查詢無法走索引,導致全表掃描,效率低下,
如果按時間ID進行表分割槽,查詢會走索引,但是時間都是按範圍range,操作會集中幾個表,讀寫壓力就很明顯
b,當業務需要查詢使用者某一時間段的訂單
c,當業務需要.....
需要把所有業務都考慮進去

2、分表
分表的做法和表分割槽相同,不同的是需要在程式碼中實現這個功能。做法是先建立分表,然後在程式中寫分表程式碼邏輯。
比如需要對訂單表分表,程式碼中就會按訂單ID(也可以任何欄位)進行範圍、或者hash取餘計算該訂單ID所處於的表,如果使用hash,可以使用一致性hash分表,避免hash取模方式在表增刪時遷移全部資料。
同樣,分表也需要集合業務,而且更加麻煩
單純就技術看:
如果按訂單ID進行hash,操作分佈多個表,但是在拓展時,就很麻煩,需要把原來的資料再重新匯入所有節點,這裡很消耗時間,關鍵是導致系統很長的不可用時間
如果按訂單ID進行範圍range,操作集中某幾個表,拓展時,很方便
這裡和表分割槽的技術優缺點相同。
綜合結合看:
a,當業務需要根據時間來查詢
如果按訂單ID進行表分割槽,無論是範圍,還是Hash,都無法根據時間進行查詢,只有全表掃描
如果按時間ID進行表分割槽,基本是按範圍分表,可以定位時間範圍。但是業務肯定會用訂單ID來查詢,而程式碼是根據時間ID做範圍分表,等於說根據訂單ID查詢的業務就不可用了。
b,當業務需要查詢使用者某一時間段的訂單
c,當業務需要.....
需要把所有業務都考慮進去


從這裡可以看到,單純做庫內的分表,mysql自帶的表分割槽適應度更高,分表的做法只適合於沒有複雜的業務、多維度的查詢。
一定要和業務結合起來,不然會遇到分了表後,業務無法執行的尷尬場面。

分庫

在資料庫中進行進行分庫,有兩個辦法
1、程式碼分庫
在程式碼中進行範圍、或者hash取餘計算該訂單ID所處於的庫,如果使用hash,最好是一致性hash分庫,避免hash取模方式在節點增刪時遷移全部資料。
單純就技術看:
優點:計算簡單,
缺點:增刪庫時,需要修改程式碼,並且需要遷移資料
2、單獨建庫建表,存放資料對應位置
單純就技術看:
優點:可拓展性強
缺點:多次查詢,效率低下,資料是否遷移看業務

綜合結合看:
無論程式碼分庫還是表存放位置,都存在跨庫查詢,已經分散式事務的問題,這裡一定要綜合業務,梳理流程,避免分散式事務。

分庫分表
在資料庫中進行進行分庫分表,有兩個辦法
1、程式碼分庫
a、程式碼分庫+表分割槽
像這種組合的分庫,一定要考慮到後期拓展的問題,如果是按範圍,就沒問題,直接增庫,如果是按hash,就需要把所有的資料全部匯出,再匯入,時間代價很大。
優點:只需一層計算資料位置,表分割槽管理簡單
缺點:需要遷移資料時,表分割槽較麻煩
這裡沒有寫一致性hash分庫+表分割槽,因為組合不能起到應有的效果。例如,分庫使用一致性Hash,而表分割槽是hash,兩邊的演算法不一致,資料無法對應, 就只能全部遷移了。

b、程式碼分庫+分表
一種是hash分庫 + hash分表,這個方法和上面的a方法相比,拓展時的都存在資料遷移時間過長,不同的是,a方法的表分割槽管理起來更簡單。
一種是一致性hash分庫 + 一致性hash分表,相比較,一致性Hash不易理解,有難度,遷移需要玩完備的方案,很繁瑣,但是拓展時,只需要遷移部分資料即可。
優點:自由度高
缺點:多層計算,維護難度大
這裡沒有寫一致性hash和hash分表的組合,因為一致性hash要求演算法一致。如果演算法不同,在資料遷移時,很可能就會遷移全部資料,甚至資料混亂。
2、建庫建表,存放資料對應的DB位置和表位置


注意:
分庫分表中可能遇到跨庫查詢或者分散式事務的問題,比如使用者ID為1的資料在庫A,使用者1的訂單資料在庫B,可以將使用者1的關聯訂單資料在插入時選擇使用者1所在的庫A,這樣就能避免分散式查詢和事務的問題。