一篇文章搞懂MySQL分表

背景

企業開發中經常會遇見某個業務使用頻繁,導致數據量特別大,而MySQL的單表承載的數據量有限,一般在1000萬以內,字段多一些還會更少,我們解決這種業務就需要對數據進行拆分,也叫sharding ,將一個表拆分多個表,或者多個數據庫,本次就介紹一下分表,知道分表邏輯分庫也就不再是個難事。

幾個概念

拆分因子:拆分因子也就是我們要按照什麼維度拆分,比如,按照用戶維度拆分,還是按照商戶維度,還是其他,這裏的用戶和商戶就是拆分因子,拆分因子的選取和業務強綁定,需要重點考慮。

哈希:也叫散列,百度百科中叫做將任意長度的輸入,通過散列算法變換成固定長度的輸入。

拆分因子選擇

因子選擇,要看這個表所支撐的業務

舉例1、京東的京豆

京豆是屬於用戶維度的,我們的操作都是查詢某個人的京豆,所以這個京豆庫存流水信息就可以按照用戶維度進行拆分,保證同一個人的京豆都存儲在同一張表裏面。

舉例2、電商的商品信息

商品信息屬於商家維度,我們一般都是進到一個店鋪,查看這個店鋪有哪些商品,商家查看自己的商品,所以這個商品信息就可以按照商家維度拆分,保證同一個商家的信息在同一表裏面。

極端例子:訂單表

訂單表即屬於商家,又屬於用戶,此時我們的選擇是優先用戶,可以按照用戶維度進行拆分,其次通過冗餘索引或冗餘數據來爲商戶提供服務,比如創建一套商戶維度的數據,然後商戶維度數據採用異步非實時的機制進行同步數據,

拆分方法

如果你的業務是按照時間進行分表,每隔一段時間創建一個新表的話,就沒有具體的拆分方式了,一定時間創建一個新表就可以了,但如果是有拆分因子,可以按照如下步驟考慮:

1、預估容量

預估該系統要支撐幾年,大概的一個數據量,按照每個表1000w左右進行評估,如果未來5年可以達到1億數據,那麼拆分10張表即可,加上一定的上浮空間,一般用2的倍數,拆分成16張就夠了。

2、考慮擴展性

如果我們16張表不夠用的時候,該怎麼辦,那32張是否足夠,如果提前做好擴展性。

實踐

比如每個訂單,都給用戶發放一定的獎勵金,我們要記錄每次發放的獎勵金信息,我們按照用戶維度進行分表;

1、每天100w訂單,也就100w條記錄

2、系統支撐5年,5*365*100w 約等於 18.25億

3、每張表最多存1000w數據,大約182張表

考慮到擴展性 我們準備最多分256張表(2的倍數)可以先拆分出16張表,隨着業務擴展最多分256張

表的命名,bounty_001,bounty_016,bounty_032 ... bounty_240 累計16張表,選擇等步長爲了每個表之間可以做擴展(稍後講到)

定位數據應該存儲的表

一致性HASH的方式,大家可以自行百度一致性Hash算法

hash(userId)%256 = shardIndex ;對用戶標識進行hash,然後除以256,取餘數;

hash是哈希算法,推薦guava工具包有幾個hash算法實現,

256是因爲我們最多要拆分256張表,取餘數就是爲了定位數據需要存到那個後綴的表中。

可以維護一套餘數與表之間的映射

1->bounty_001

2->bounty_001

.....

15->bounty_001

16->bounty_016

17->bounty_017

這樣當計算出餘數,就能從這個映射中知道應該存儲到哪張表裏面,通過動態組裝SQL,變更表名,直接插入到對應的數據庫即可。

擴容

當然我們可以直接一次性拆分256張表或者更多直接滿足業務需求,但那樣也會給我們的系統的維護帶來一定的複雜度,畢竟每張表我們都要處理,所以常規都是按照上面的做法,先少分幾張,保證業務應用,隨着業務的增長再繼續擴容。

上例中,如果我們需要擴容,我們可以在後綴爲001和016之間,新建bounty_008,然後修改映射關係,將餘數8-15的數據存儲到bounty_008表中,同時將bounty_001表中的數據,複合餘數8-15之間的數據,轉移到bounty_008中,這就完成了數據表的擴容;

以上就是簡單的數據庫分表實踐,是不是很簡單,實際業務可能會遇到更復雜的,就像舉例3中的場景。那就需要附加索引或者異步冗餘,或者藉助其他方式如ES等來解決。寫的不好大家多多指正

分庫分表

發佈了27 篇原創文章 · 獲贊 14 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章