資料庫分庫分表策略

數據庫分庫與分表

我們知道每臺機器無論配置多麼好它都有自身的物理上限,所以當我們應用已經能觸及或遠遠超出單臺機器的某個上限的時候,我們惟有尋找別的機器的幫助或者繼續升級的我們的硬件,但常見的方案還是通過添加更多的機器來共同承擔壓力。

我們還得考慮當我們的業務邏輯不斷增長,我們的機器能不能通過線性增長就能滿足需求?因此,使用數據庫的分庫分表,能夠立竿見影的提升系統的性能,關於為什麼要使用數據庫的分庫分表的其他原因這裡不再贅述,主要講具體的實現策略。請看下邊章節。

二、分表實現策略

關鍵字:用戶ID、表容量

對於大部分數據庫的設計和業務的操作基本都與用戶的ID相關,因此使用用戶ID是最常用的分庫的路由策略。用戶的ID可以作為貫穿整個系統用的重要字段。因此,使用用戶的ID我們不僅可以方便我們的查詢,還可以將數據平均的分配到不同的數據庫中。(當然,還可以根據類別等進行分表操作,分表的路由策略還有很多方式)

接著上述電商平臺假設,訂單表order存放用戶的訂單數據,sql腳本如下(只是為了演示,省略部分細節):

數據庫分庫分表策略

當數據比較大的時候,對數據進行分表操作,首先要確定需要將數據平均分配到多少張表中,也就是:表容量

這裡假設有100張表進行存儲,則我們在進行存儲數據的時候,首先對用戶ID進行取模操作,根據 user_id%100 獲取對應的表進行存儲查詢操作,示意圖如下:

數據庫分庫分表策略

例如,user_id = 101 那麼,我們在獲取值的時候的操作,可以通過下邊的sql語句:

select * from order_1 where user_id= 101

其中,order_1是根據 101%100 計算所得,表示分表之後的第一章order表。

注意:

在實際的開發中,如果你使用MyBatis做持久層的話,MyBatis已經提供了很好得支持數據庫分表的功能,例如上述sql用MyBatis實現的話應該是:

接口定義:

數據庫分庫分表策略

xml配置映射文件:

數據庫分庫分表策略

其中${tableNum} 含義是直接讓參數加入到sql中,這是MyBatis支持的特性。

注意:

另外,在實際的開發中,我們的用戶ID更多的可能是通過UUID生成的,這樣的話,

我們可以首先將UUID進行hash獲取到整數值,然後在進行取模操作。

三、分庫實現策略

數據庫分表能夠解決單表數據量很大的時候數據查詢的效率問題,但是無法給數據庫的併發操作帶來效率上的提高,因為分表的實質還是在一個數據庫上進行的操作,很容易受數據庫IO性能的限制。

因此,如何將數據庫IO性能的問題平均分配出來,很顯然將數據進行分庫操作可以很好地解決單臺數據庫的性能問題。

分庫策略與分表策略的實現很相似,最簡單的都是可以通過取模的方式進行路由。

還是上例,將用戶ID進行取模操作,這樣的話獲取到具體的某一個數據庫,同樣關鍵字有:

用戶ID、庫容量

路由的示意圖如下:

數據庫分庫分表策略

上圖中庫容量為100。

同樣,如果用戶ID為UUID請先hash然後在進行取模。

四、分庫與分表實現策略

上述的配置中,數據庫分表可以解決單表海量數據的查詢性能問題,分庫可以解決單臺數據庫的併發訪問壓力問題。

有時候,我們需要同時考慮這兩個問題,因此,我們既需要對單表進行分表操作,還需要進行分庫操作,以便同時擴展系統的併發處理能力和提升單表的查詢性能,就是我們使用到的分庫分表。

分庫分表的策略相對於前邊兩種複雜一些,一種常見的路由策略如下:

1、中間變量 = user_id%(庫數量*每個庫的表數量);

2、庫序號 = 取整(中間變量/每個庫的表數量);

3、表序號 = 中間變量%每個庫的表數量;

例如:數據庫有256 個,每一個庫中有1024個數據表,用戶的user_id=262145,按照上述的路由策略,可得:

1、中間變量 = 262145%(256*1024)= 1;

2、庫序號 = 取整(1/1024)= 0;

3、表序號 = 1%1024 = 1;

這樣的話,對於user_id=262145,將被路由到第0個數據庫的第1個表中。

示意圖如下:

數據庫分庫分表策略

五、分庫分表總結

關於分庫分表策略的選擇有很多種,上文中根據用戶ID應該是比較簡單的一種。其他方式比如使用號段進行分區或者直接使用hash進行路由等。有興趣的可以自行查找學習。

關於上文中提到的,如果用戶的ID是通過UUID的方式生成的話,我們需要單獨的進行一次hash操作,然後在進行取模操作等,其實hash本身就是一種分庫分表的策略,使用hash進行路由策略的時候,我們需要知道的是,也就是hash路由策略的優缺點,優點是:數據分佈均勻;缺點是:數據遷移的時候麻煩,不能按照機器性能分攤數據。

上述的分庫和分表操作,查詢性能和併發能力都得到了提高,但是還有一些需要注意的就是,例如:原本跨表的事物變成了分佈式事物;由於記錄被切分到不同的數據庫和不同的數據表中,難以進行多表關聯查詢,並且不能不指定路由字段對數據進行查詢。分庫分表之後,如果我們需要對系統進行進一步的擴陣容(路由策略變更),將變得非常不方便,需要我們重新進行數據遷移。


最後需要指出的是,分庫分表目前有很多的中間件可供選擇,最常見的有MyCat、sharding-sphere等。


分享到:


相關文章: