1. 程式人生 > >mysql千萬資料級分表設計及實現方案

mysql千萬資料級分表設計及實現方案

    針對系統資料表日漸增長的資料量,分庫分表是減少資料庫壓力,增加db操作效率的常見解決方案。就目前專案系統而言,資料量級基本多張表已達3kw至6kw的量級。下面對筆者針對系統db結構,結合O2O業務特性整理的分表設計思路及實踐方案的討論。

設計思路:

1、首先確定是否要分表:就一般系統而言,資料量達到kw級別,慢sql數量增多,基本就需要考慮分表操作。

2、確定分成幾張表:這個根據資料增長量估算,簡言之,當前資料量分成多少份,結合當前業務量,估算本次分表後,可滿足多少年內穩健的資料服務。

3、拆分方案:就拆分方案而言,一般採取兩種思路:

    1)一是根據自增主鍵進行雜湊取模,將資料均分到n張表中;該方案最簡單,且最合適,拆分後資料分佈均勻。

    2)二是無自增主鍵,選取的分表id由特定的方式生成,則需先確定分表id生成邏輯,根據該邏輯確定取模計算的邏輯,以保證資料均分。

案例分析:

下面採用專案中兩個case分表說明:

case1 支付詳情表:

1、資料表結構分析:6kw量級、自增主鍵、資料插入查詢多,更新少、日增量3k條

2、方案設計:採用自增主鍵取模8,分為8張表。

case2 使用者積分表:

1、資料表結構分析:4kw資料量級、主鍵 id非自增、讀多寫少,常根據uid進行查詢

2、方案設計:

    採用uid作為分表鍵,研究uid生成邏輯為16位 (時間戳+機器ID+業務編碼(細節不贅述);確定分表計算方案為

右移7,保證取模方式合理,資料均分到表中。

3、實現細節

1)分表前,建立新表,將老表資料同步到新表(DTS阿里雲dba方案)

2)修改程式碼,讀取老表資料,同時雙寫(老表成功即為成功)

3)修改程式碼,讀新表,繼續雙寫(新表寫成功即為成功)優化:修改讀取配置,開關--切換讀取新老表資料

4)穩定後,停止老表讀寫

4、問題分析

問題1:根據uid進行分表,同一個uid的所有記錄都會落入同一張表中。若該uid為高頻使用者,則該uid假設有1w條訂單記錄,這極有可能導致針對該uid的訂單查詢緩慢;另外遇到訂單id或其他維度的key查詢,也會導致熱點問題。而熱點資料又大概率上會大量增長。

問題2:聯合查詢問題,分表後,如何返回某商家所有使用者訂單。

問題1解決方案:熱點問題可通過對熱點資料進行快取,例如將使用者的資料快取起來。擴充套件問題:快取與db的資料一致性及及時性(在此不做討論)

問題2解決方案:根據商家id可進行異構索引表建立,即記錄uid表的商家維度操作,將uid、商家id、訂單id等作為一張全新索引表,記錄關聯關係。查詢時可通過先查詢索引表,找到對應分表鍵,再根據分表鍵單表路由。

5、注意:

    1)資料儘可能平均拆分,避免熱點問題;如遇熱點問題,採用對熱點資料進行快取等方式減少熱點資料訪問壓力

    2)減少全域性掃描,針對帶有分庫分表鍵的sql直接經路由後查指定表,但針對無分表主鍵,例如case中商家所有資料,則只能通過查詢所有表後,再將資料聚合後返回-事務邊界過大。此時可通過建立索引表,用於記錄所有表的crud操作(空間換時間)。建立以商家id為索引的表,通過先查賣家所有記錄,得到所有使用者id,再拿uid 為key去表裡查就變為帶有分庫分表鍵的查詢。極致的還可能建立兩張表,除了分表key不一樣,其他欄位均相同。即可通過uid、商家id進行查詢。但冗餘太大如無必要,一般不採取全表複製。