資料庫分庫分表策略

2021-09-13 14:28:10 字數 3873 閱讀 1287

一、背景:

系統剛開始的時候,資料庫都是單庫單錶結構。隨著業務量的增加進行第一次資料庫公升級,根據業務垂直拆分資料庫,這樣多變成多個業務資料庫,每個資料庫裡面還是單錶結構。接下來,繼續隨著業務量的繼續增加,單錶已經很難承受資料量,就要進行分表,這個時候就是,多個業務庫,每個業務庫下對需要分表的表進行分表。再接下來,隨著應用的增加,資料庫io,磁碟等等都抗不住了,就要把分表的表分到多個庫,這樣就形成了如下的結構。 

重點:本文主要討論的是分庫分表的策略,也就是分庫分表的規則或者說是演算法。

二、分庫分表的依據--分庫分表字段的選擇

分庫分表首先要確定根據哪個字段、或者哪幾個字段進行路由,一般的原則是按使用頻率最高維度的字段去分庫分表,盡量保證高使用維度下只查詢單錶。 

常用的字段有主鍵id,使用者id,時間,商戶id,產品id,業務型別等等 

三、分庫分表策略

主要原理:分割槽、取模、資料路由表

1. 按照時間區間

1)基本原理: 

一定區間內時間產生的資料放到一張表裡面,多個時間區間的表放到乙個庫裡面 

2)簡單例子: 

單庫多表結構,按月分表可以這樣,user_201601,user_201602,...,user_201612這種結構。按年分表可以這樣,user_2016,user_2017,...這種。 

3)多庫多表演算法: 

比如按天分表,每天一張表,當單庫超過100張表的時候,進行分庫到下一張表。那麼假如第一張報表在庫bd0,表名是user_20160201。從db0.user_20160201,..到db0.user_20160511就100張表了,接下來就要進行分庫了,進入20160512,就是db1.user_20160512,這個演算法就是上線的時候定乙個上線日期,具體演算法如下 

庫id = (當前日期 - 上線日期)/ 100

表id = user_yyyymmdd 

注:好處是可以直接根據時間經過簡單計算定位到哪個庫和哪個表

還有一種演算法:

庫id = (當前日期 - 上線日期)/ 100 

表id = (當前日期 - 上線日期) % 100 

表名如下: db0.user_0001, user_0002,....,user_01000。 

注:表名和庫名都要經過計算,比較麻煩

4)按月分表,每個月一張表;這種情況,一般就不用分庫了,一年12張表說明量也不會特別大,如果量特別大,或者是熱點資料,可以一年分乙個庫,具體演算法和上面差不多。 

5)按季度分表,基本不用分庫。 

6)按年分表,肯定不用分庫了,沒有必要了。 

2. 按照主鍵id區間

對於自增的主鍵id,可以按照id區間進行分表,以1000萬資料量為分界線,對線性的id進行切割分表,每漲到1000萬資料,分到下一張表,超過一定數目的表,進行分庫。 

庫id = 主鍵id / 1000萬 / 100

表id = 主鍵id / 1000萬 % 100 

如:db0.user_0000,...,db0.user_0099, db1.user_0000,...,db1.user_0099

3. 按照指定欄位hash後再取模

如果要取模的字段不是整數型,要先hash後,再通過取模演算法,算出在哪個庫和那個表。具體演算法,參照下面的按使用者id取模。 

4. 按照使用者id取模

這裡把按照使用者id取模單獨拎出來,因為就使用而言,是使用場景最多的情況,很多時候都是使用者相關資料量最大,需要分庫分表,查詢維度更多也是按照使用者來查詢,所以對使用者取模,讓同乙個使用者的資料落到一張表裡面,再好不過了。 

案例:假設使用者id是整數型的。庫數量要分4庫,每個庫表數量8表,一共32張表。 

原理講解:

一共要分4庫,8表,共32張表,也就是1到32的使用者id要平均分配到每張表應該有一條資料,這樣就有兩種分法。 

1) 1到8是第乙個庫,9到16第二個庫,17到24第三個庫,25到32是第四個庫,每個庫裡面表的編號都是0到3,這個原則是乙個庫裡面乙個乙個分,分完再下乙個庫乙個乙個分,保證不重複,不漏掉。

2)1,5,9這樣每隔4個乙個庫,2開頭隔4個乙個庫,這個原則是乙個庫分乙個,在分下乙個庫,一圈走完,再在第一庫沒分到的表繼續分,也保證了不重複,不漏掉原則。

庫id = userid % 庫數量4

表id = userid / 庫數量4 % 表數量8 

或者 庫id = userid / 表數量4 % 庫數量4 

表id = userid % 表數量8

演算法圖示如下:

5. 資料路由表

如果分庫分表的演算法很複雜,可以通過路由表+程式演算法,來儲存和計算分庫分表規則,不過一般不建議,分庫分表搞得太複雜,不便於維護和查詢問題 

四、各個方案對比

分割槽演算法

優點:線性擴容,平滑擴容,不需要資料遷移 

缺點:存在熱點資料,非時間維度查詢多的情況,聚合複雜 

建議:冷資料,使用者維度查詢少,且資料量大的情況用分割槽演算法 

取模演算法

優點:同乙個熱點的資料可以做到乙個表裡面,查詢方便 

缺點:擴容不是很方便,需要資料遷移 

建議:使用者維度查詢多,熱點維度查詢多的情況,建議使用 

注:

分庫分表的核心是未來資料量的預估,根據預估和實際使用情況來確定分庫分表方案,一般像訂單類資料以使用者維度取模分表最好,商品資料以商戶取模最好,簽到等活動流水資料時間分割槽最好。 

取模方案擴容的解決:一、可以提前按照預估方案建立庫和表,前期放到乙個db,後期遷移,或者一次性弄好 二、可以按照預估的方案去確定分庫和分表的字尾id,但是前期只建立一部分庫和表。例如:最終4庫,每個庫16個表。字尾應該是0000----0315共64個表的字尾,前期可以乙個庫,4個表,也就是所有資料都在這個四張表裡面。 

0000--0003-----》0000表 

0100--0103-----》0000表 

0200--0203-----》0000表 

0300--0303-----》0000表 

0004--0007-----》0004表 

0104--0107-----》0004表 

0204--0207-----》0004表 

0304--0307-----》0004表 

0008--0011-----》0008表 

0108--0111-----》0008表 

0208--0211-----》0008表 

0308--0311-----》0008表 

0012--0015-----》0012表 

0112--0115-----》0012表 

0212--0215-----》0012表 

0312--0315-----》0012表 

後續可以二分法,遷移資料,擴容。 

資料庫 分庫分表以及切分策略

隨著業務和資料量的增長,單庫的io壓力越來遠大,可將單一資料庫的資料分散到多個資料庫中,來緩解資料庫的訪問壓力。資料庫切分的兩種方式 垂直分庫 根據業務的耦合程度,將關聯度低的表儲存在不同的資料庫中。與微服務的做法相似,每個微服務使用單獨的資料庫。垂直分表 基於資料庫中的列進行。新建一張擴充套件表,...

資料庫分庫分表

1 基本思想之什麼是分庫分表?從字面上簡單理解,就是把原本儲存於乙個庫的資料分塊儲存到多個庫上,把原本儲存於乙個表的資料分塊儲存到多個表上。2 基本思想之為什麼要分庫分表?資料庫中的資料量不一定是可控的,在未進行分庫分表的情況下,隨著時間和業務的發展,庫中的表會越來越多,表中的資料量也會越來越大,相...

資料庫分庫 分表

分庫的優點是 實現簡單,庫與庫之間界限分明,便於維護,缺點是不利於頻繁跨庫操作,單錶資料量大的問題解決不了。分表的優點是 能解決分庫的不足點,但是缺點卻恰恰是分庫的優點,分表實現起來比較複雜,特別是分表規則的劃分,程式的編寫,以及後期的 資料庫拆分移植維護。實際應用中,一般網際網路企業的路線都是先分...