分庫分表使用場景及設計方式


一. 分表

      場景:對於大型的互聯網應用來說,數據庫單表的記錄行數可能達到千萬級甚至是億級,並且數據庫面臨着極高的並發訪問。采用Master-Slave復制模式的MySQL架構,只能夠對數據庫的讀進行擴展,而對數據庫的寫入操作還是集中在Master上,並且單個Master掛載的Slave也不可能無限制多,Slave的數量受到Master能力和負載的限制。

  因此,需要對數據庫的吞吐能力進行進一步的擴展,以滿足高並發訪問與海量數據存儲的需要!

  對於訪問極為頻繁且數據量巨大的單表(百萬到千萬級別)來說,我們首先要做的就是減少單表的記錄條數,以便減少數據查詢所需要的時間,提高數據庫的吞吐,這就是所謂的分表!

  在分表之前,首先需要選擇適當的分表策略,使得數據能夠較為均衡地分不到多張表中,並且不影響正常的查詢! 

  對於互聯網企業來說,大部分數據都是與用戶關聯的,因此,用戶id是最常用的分表字段。因為大部分查詢都需要帶上用戶id,這樣既不影響查詢,又能夠使數據較為均衡地分布到各個表中(當然,有的場景也可能會出現冷熱數據分布不均衡的情況),如下圖:

  假設有一張表記錄用戶購買信息的訂單表order,由於order表記錄條數太多,將被拆分成256張表

  拆分的記錄根據user_id%256取得對應的表進行存儲,前台應用則根據對應的user_id%256,找到對應訂單存儲的表進行訪問(即id除以256余數為0則查0號表)

  這樣一來,user_id便成為一個必需的查詢條件,否則將會由於無法定位數據存儲的表而無法對數據進行訪問。

  注:拆分后表的數量一般為2的n次方,就是上面拆分成256張表的由來!

舉例:

假設order表結構如下:

 1 create table order_(
 2  order_id bigint(20) primary key auto_increment,
 3  user_id bigint(20),
 4  user_nick varchar(50),
 5  auction_id bigint(20),
 6  auction_title bigint(20),
 7  price bigint(20),
 8  auction_cat varchar(200),
 9  seller_id bigint(20),
10  seller_nick varchar(50)
11 )

  那么分表以后,假設user_id = 257,並且auction_id = 100,需要根據auction_id來查詢對應的訂單信息,則對應的SQL語句如下:

select * from order_1 where user_id=257 and auction_id = 100;

  其中,order_1是根據257%256計算得出,表示分表之后的第一張order表。

二. 分庫

  場景:分表能夠解決單表數據量過大帶來的查詢效率下降的問題,但是,卻無法給數據庫的並發處理能力帶來質的提升。面對高並發的讀寫訪問,當數據庫master服務器無法承載寫操作壓力時,不管如何擴展slave服務器,此時都沒有意義了。

  因此,我們必須換一種思路,對數據庫進行拆分,從而提高數據庫寫入能力,這就是所謂的分庫!

  與分表策略相似,分庫可以采用通過一個關鍵字取模的方式,來對數據訪問進行路由,如下圖所示:

 

  還是之前的訂單表,假設user_id 字段的值為258,將原有的單庫分為256個庫,那么應用程序對數據庫的訪問請求將被路由到第二個庫(258%256 = 2)。

三. 分庫分表

  場景:有時數據庫可能既面臨着高並發訪問的壓力,又需要面對海量數據的存儲問題,這時需要對數據庫既采用分表策略,又采用分庫策略,以便同時擴展系統的並發處理能力,以及提升單表的查詢性能,這就是所謂的分庫分表。

    分庫分表的策略比前面的僅分庫或者僅分表的策略要更為復雜,一種分庫分表的路由策略如下:

  1. 中間變量 = user_id % (分庫數量 * 每個庫的表數量)
  2. 庫 = 取整數 (中間變量 / 每個庫的表數量)
  3. 表 = 中間變量 % 每個庫的表數量

 

  同樣采用user_id作為路由字段,首先使用user_id 對庫數量*每個庫表的數量取模,得到一個中間變量;然后使用中間變量除以每個庫表的數量,取整,便得到對應的庫;而中間變量對每個庫表的數量取模,即得到對應的表。

分庫分表策略詳細過程如下:

 假設將原來的單庫單表order拆分成256個庫,每個庫包含1024個表,那么按照前面所提到的路由策略,對於user_id=262145 的訪問,路由的計算過程如下:

  1. 中間變量 = 262145 % (256 * 1024) = 1
  2. 庫 = 取整 (1/1024) = 0
  3. 表 = 1 % 1024 = 1

 這就意味着,對於user_id=262145 的訂單記錄的查詢和修改,將被路由到第0個庫的第1個order_1表中執行!!!

四,橫分縱分

分表又分為橫向分表和縱向分表

1)縱向分表

   將本來可以在同一個表的內容,人為划分為多個表。(所謂的本來,是指按照關系型數據庫的 第三范式要求,是應該在同一個表的。)
分表理由: 根據數據的活躍度進行分離,(因為不同活躍的數據,處理方式是不同的)
 
案例:
  對於一個博客系統,文章標題,作者,分類,創建時間等,是 變化頻率慢查詢次數多,而且最好有很好的實時性 的數據,我們把它叫做 冷數據。而博客的瀏覽量,回復數等,類似的統計信息,或者別的 變化頻率比較高的數據,我們把它叫做 活躍數據。所以,在進行數據庫結構設計的時候,就應該考慮分表,首先是 縱向分表的處理。
這樣縱向分表后:
  首先存儲引擎的使用不同, 冷數據使用MyIsam 可以有更好的查詢數據。 活躍數據,可以使用Innodb,可以有更好的更新速度。
  其次, 對冷數據進行更多的 從庫配置,因為更多的操作時查詢,這樣來加快查詢速度。 對熱數據,可以相對有更多的 主庫的橫向分表處理
  其實,對於一些 特殊的活躍數據,也可以考慮使用memcache , redis之類的緩存,等累計到 一定量再去更新數據庫。或者mongodb 一類的nosql數據庫,這里只是舉例,就先不說這個。

橫向分表

  字面意思,就可以看出來,是把大的表結構,橫向切割為同樣結構的不同表,如,用戶信息表,user_1,user_2等。 表結構是完全一樣,但是,根據某些特定的規則來划分的表,如根據用戶ID來取模划分。
  分表理由: 根據數據量的規模來划分,保證單表的容量不會太大,從而來保證單表的查詢等處理能力

案例:

  同上面的例子,博客系統。當博客的量達到很大時候,就應該采取橫向分割來降低每個單表的壓力,來提升性能。例如博客的冷數據表,假如分為100個表,當同時有100萬個用戶在瀏覽時,如果是單表的話,會進行100萬次請求,而現在分表后,就可能是每個表進行1萬個數據的請求(因為,不可能絕對的平均,只是假設),這樣壓力就降低了很多很多。

 

https://blog.csdn.net/yuxianjun2012/article/details/54846136 

https://blog.csdn.net/winy_lm/article/details/50708493

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM