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

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

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

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

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

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

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

 

2、大數據如何分庫分表

根據您提供的文本,以下是對“使用uid取模運算進行分庫分表”方案的總結:

方案概述
該方案是業界常用的訂單數據分庫分表方法,核心是以用户ID(uid)作為分片鍵進行取模運算,將數據均勻分散到多個數據庫和表中。

具體實現規則
1. 庫定位:使用用户ID末尾4位數字 Mod 32(即除以32取餘數)。餘數範圍0-31,對應32個庫,例如 `order_db_0` 到 `order_db_31`。
2. 表定位:分兩步計算:
* 先將用户ID末尾4位數字 Dev 32(即除以32後向下取整)。
* 再將得到的整數 Mod 32(除以32取餘數)。餘數範圍0-31,對應每個庫內的32張表,例如 `order_tb_0` 到 `order_tb_31`。
3. 數據規模:按此規則(32庫 × 32表),可建立總計1024張表。通過控制單表數據量(如1千萬至5千萬行),系統可支撐海量數據。

優點
* 實現簡單:在程序層面進行取模運算即可,開發便捷。
* 數據分佈均勻:通過取模能使數據相對均勻地分散到各個庫和表,有助於避免單個庫成為性能瓶頸。
* 查詢效率高(針對用户維度):由於同一用户的所有訂單通過其固定ID計算後,總會落在同一個庫的同一張表中,因此查詢指定用户的所有訂單時,無需跨庫或跨表查詢,性能高。

缺點
* 擴容複雜:當需要增加數據庫節點(擴容)時,原有的取模規則會發生變化,需要進行數據遷移,操作繁瑣。
* 最佳實踐:為減少遷移量,擴容通常以倍數形式進行(例如從8庫擴至16庫,再至32庫)。
* 數據可能分佈不均:雖然取模能使數據整體分散,但無法避免因業務差異導致的數據傾斜。例如,某些用户(或其ID段)下單量極大,其所有訂單仍會集中到同一張表,可能導致該單表數據量過早達到上限。

總結與權衡
該方案是一種在實現複雜性、查詢性能與可擴展性之間取得平衡的實用選擇。它用相對簡單的邏輯解決了用户維度查詢的核心痛點,雖然存在擴容麻煩和數據潛在傾斜的問題,但其優勢在多數業務場景下更為突出,因此被廣泛採用。業界通常的應對策略是接受其缺點,優先滿足當前業務性能需求,待未來數據量真正達到瓶頸時,再考慮更復雜的解決方案。

 

3、大眾點評訂單系統分庫分表實踐

唯一ID方案:時間戳+用户標識碼+隨機數。好處:自帶分庫規則,這裏的用户標識碼即為用户ID的後四位,在查詢的場景下,只需要訂單號就可以匹配到相應的庫表而無需用户ID,只取四位是希望訂單號儘可能的短一些,並且評估下來四位已經足夠。
可排序,因為時間戳在最前面。

採用Mod來切分。

數據水平切分後我們希望是一勞永逸或者是易於水平擴展的,所以推薦採用mod 2^n這種一致性Hash。
以統一訂單庫為例,我們分庫分表的方案是32*32的,即通過UserId後四位mod 32分到32個庫中,同時再將UserId後四位Div 32 Mod 32將每個庫分為32個表,共計分為1024張表。
線上部署情況為8個集羣(主從),每個集羣4個庫。

場景一:數據庫性能達到瓶頸
方法一
按照現有規則不變,可以直接擴展到32個數據庫集羣。

方法二
如果32個集羣也無法滿足需求,那麼將分庫分表規則調整為(32*2^n)*(32/2^n),可以達到最多1024個集羣。

 

用户端:根據用户id的hash值對數據庫的數量進行取模找到對應的數據庫->根據用户id的hash值除以對錶的數量,然後在對錶的數量進行取模即可找到對應的表

單獨為商家B端設計了一套表(C端和B端是獨立的):在下單的時候把隊友的訂單號發送到MQ裏,商家可以去消費這個MQ,然後根據訂單號獲取訂單信息,然後再把訂單信息插入到商户的數據庫表當中。商户的 路由策略 和用户的 路由策略 是一樣的。

 

5、訂單表每天新增500w數據,分庫分表如何設計?

1.1天500萬,那麼1年就是18億,我們按照2年的增量來算就是大概40億
2.在預留一些空間,按照50億來算
3.那麼需要使用32個庫,每個庫32張表,那麼一共就是1024張表,每個表存500萬數據
4.使用orderId(訂單id)當做分片鍵,使用一致性hash算法來分配,要插入到那個數據庫的那個表中
5.當訂單的數據超過了2年,那麼使用冷熱分離的方案或者使用tidb在線擴容數據庫來解決
6.熱庫數據保留一年,1年以後遷移到冷庫,冷庫保存2年,2年後,進行數據歸檔

 

6、【架構設計】高併發訂單系統分庫分表方案

一、分片策略選擇(核心決策)

1. 按用户ID分片
適用場景:用户維度的查詢頻繁(如查詢個人訂單列表、分頁展示)。
實現方式:

分庫:user_id % 64 路由到64個庫(預留擴容空間)。
分表:每個庫內按user_id % 1024 分1024張表,單表控制在千萬級數據量。

優點:同一用户數據集中存儲,避免跨分片查詢。
缺點:超級買家可能導致數據傾斜(如某用户訂單量極大)。
優化:冷熱分離,3個月內熱數據存MySQL,歷史數據歸檔至HBase/ES。

2. 按訂單號分片

適用場景:需均勻分散寫入壓力,避免熱點。
實現方式:

基因分片法:訂單號末尾嵌入用户ID哈希值(如訂單號=時間戳+用户ID後4位+隨機數),直接根據訂單號定位庫表。
分庫分表:hash(order_id) % (庫數量×表數量) 計算中間變量,再拆解庫表序號。

優點:數據分佈均勻,支持高併發寫入。
缺點:按用户ID查詢需跨分片,需額外設計索引表。

3. 按時間分片

適用場景:時間範圍查詢為主(如統計月度訂單)。
實現方式:按月分庫(orders_202301),庫內再按用户ID或訂單號分表。
缺點:新表寫入熱點,歷史數據查詢需跨庫。
優化:結合哈希後綴分散寫入(如訂單號添加隨機數)。

 

二、全局ID生成方案

  • 雪花算法(Snowflake):

64位結構:1符號位 + 41位時間戳 + 10位機器ID + 12位序列號。
問題:時鐘回撥需通過NTP同步或本地緩存解決。

  • 號段模式:

從數據庫批量獲取ID段(如每次分配1000個ID),減少DB壓力。

  • 嵌入分片信息:

在訂單號頭部添加分庫分表路由碼(如庫序號+表序號),實現無索引直接查詢。

 

三、跨分片查詢解決方案

  • 索引表機制:

建訂單號→用户ID映射表,異步寫入MQ更新,分庫分表後按訂單號取模分片。
查詢時先查索引表獲取用户ID,再路由到對應分片。

  • 數據冗餘:

多寫異構:訂單同時寫入買家庫(按user_id分片)和賣家庫(按shop_id分片),通過MQ同步數據。
字段冗餘:訂單表冗餘商家名稱、用户名稱等高頻字段,避免JOIN查詢。

  • 聚合查詢:

複雜統計(如全平台銷售額)通過ETL同步至ES或Hive離線分析。

四、熱點問題處理

  • 秒殺訂單:

獨立分片:秒殺訂單單獨分配至特定分庫,避免影響常規訂單。
本地緩存+Redis預減庫存,DB層異步落單。

  • 數據傾斜:

冷熱分離:3個月內熱數據存高性能庫,歷史數據轉冷存儲。
動態擴容:按倍數擴容(如8庫→16庫),減少數據遷移量。