當前位置: 妍妍網 > 碼農

5000w+ 的大表如何拆?億級別大表拆分實戰復盤

2024-05-16碼農

來源:juejin.cn/post/7078228053700116493

👉 歡迎 ,你將獲得: 專屬的計畫實戰 / Java 學習路線 / 一對一提問 / 學習打卡 / 每月贈書

新計畫: 仿小紅書 (微服務架構)正在更新中... , 全棧前後端分離部落格計畫 2.0 版本完結啦, 演示連結 http://116.62.199.48/ 。全程手摸手,後端 + 前端全棧開發,從 0 到 1 講解每個功能點開發步驟,1v1 答疑,直到計畫上線。 目前已更新了261小節,累計41w+字,講解圖:1806張,還在持續爆肝中.. 後續還會上新更多計畫,目標是將Java領域典型的計畫都整一波,如秒殺系統, 線上商城, IM即時通訊,Spring Cloud Alibaba 等等,

  • 前言

  • 拆表前系統狀態

  • 拆表的目標

  • 難點分析

  • 整體過程

  • 具體細節

  • 總結

  • 說點兒題外話

  • 前言

    筆者是在兩年前接手公司的財務系統的開發和維護工作。在系統移交的初期,筆者和團隊就發現,系統內有一張5000W+的大表。

    跟蹤程式碼發現,該表是用於儲存資金流水的表格,關聯著眾多功能點,同時也有眾多的下遊系統在使用這張表的數據。

    進一步的觀察發現,這張表還在以每月600W+的數據持續增長,也就是說,不超過半年,這張表會增長到1個億!

    筆者內心:(麻了)

    這個數據量,對於mysql資料庫來說是絕對無法繼續維護的了,因此在接手系統兩個月後,我們便開起了大表拆分的專項工作。(兩個月時間實際上主要用來熟悉系統、消化堆積需求了)

    拆表前系統狀態

  • 涉及到流水表流水的介面超時頻發,部份介面基本不可用

  • 每日新增流水緩慢,主要是插入資料庫的時候非常慢

  • 單表占用空間過大,DBA的資料庫監控經常報警

  • 無法對表進行變更,任何alter操作都會引起主從的高延遲和長時間鎖表

  • 拆表的目標

  • 將流水大表數據拆分至各個分表,保證每張分表數據在1000W左右(經驗上看單表1000W的量對mysql來說沒啥壓力)

  • 在拆表的前提下,針對不同介面的查詢條件進行最佳化,保證各個對外、對內介面的可用性。徹底殺死mysql慢查詢。

  • 難點分析

  • 該表的數據可以說是整個財務系統最基礎的數據,相關功能和下遊系統非常多。這要求開發、測試和上線流程必須極其嚴密,任何小失誤都會引起大問題。

  • 涉及的場景非常多。統計下來,一共有26個場景,需要改造32個mapper方法,具體需要改造的方法就更加無計其數了。

  • 數據量非常大,遷移數據的過程必須保證系統穩定。

  • 使用者較多且功能重要。分表功能上線時,必須盡量壓縮系統無法使用時長,同時需要保證系統可用性。這要求團隊必須設計完整可靠的上線流程、數據遷移方案、回滾方案、降級策略。

  • 上文提到,表的拆分勢必帶來部份介面的變化,介面的變化又會帶來其他系統的改造。如何推動其他系統進行改造,如何協調多方合作的開發、測試和上線是另一個難點。

  • 整體過程

    圖片

    具體細節

    分表中介軟體調研

    分表外掛程式:采用sharding-jdbc作為分表外掛程式。

    其優勢如下:

    1、支持多種分片策略,自動辨識=或in判斷具體在哪張分表裏。

    2、輕量級,作為maven依賴引入即可,對業務的侵入性極低。

    為提升查詢速度,在整個計畫的初期,團隊成員考慮引入ES儲存流水以提升查詢速度。

    經過與ES維護團隊的兩輪討論,發現公司提供的ES服務對於我們的業務場景並不匹配(見表),經過反復考量,最終我們放棄了引入ES的計劃,直接從資料庫查詢數據,采用每張表設定一個查詢執行緒的方式提升查詢效率。

    圖片

    分表依據的選擇

    分表的方式有很多種,有縱向分表,有橫向分表,有分為固定的幾個表儲存然後取模進行表拆分等等。總的來說,適合我們具體業務的分表方式只有橫向分表。

    因為對於資金流水這種特殊數據來說,是不能清理數據的,那麽縱向分表和拆成固定的幾個表都不能解決單表數據無限膨脹的問題。而橫向分表,可以把每張表的數據量恒定,到一定時間後可以進行財務數據歸檔。

    分表的依據一般都是根據表的某個或者某幾個欄位進行拆分,最終其實是對數據和業務分析綜合出來的結果。總的來說,原則有這幾個:

  • 盡可能選擇查詢條件裏最常出現的欄位,這樣能夠減少方法改造的工程

  • 需要考慮根據某個欄位拆分數據是否能夠均勻分布,是否能夠滿足單表1000W左右的要求

  • 該欄位必須是必現欄位,不允許出現空值

  • 綜合分析我們的數據以及業務需要,「交易時間」這個分表依據就呼之欲出了。

    首先,這個欄位作為流水最重要的欄位之一一定會出現;

    第二,如果按照交易月份進行拆表,每張表大概也就是600W-700W的數據;

    最後,有70%的查詢都附帶「交易時間」作為查詢條件。

    技術難點

    多資料來源事務問題

    sharding-jdbc在使用的時候是需要用自己的獨立資料來源的,那麽就難免出現多資料來源事務問題。

    這個我們透過自訂註解,自訂切面開啟事務,透過方法棧逐層回滾or送出的方式解決的。出於保密原則,具體程式碼細節不再展開。

    多表的分頁問題

    拆表一定會引起分頁查詢的難度增加。由於各個表查出來的數據量不等,原始的sql語句limit不再適用,需要設計一個新方法便捷的獲取分頁資訊。

    在此介紹一個分頁的思路供大家參考(團隊共同的成果,筆者不敢私自占有):

    綜合考慮業務實際與開發的復雜程度,計畫團隊決定在出現跨表查詢的情況下,每一張表采用一個執行緒進行查詢,以提高查詢效率。

    這個方案的難點在於分頁規則的轉換。例如,頁面傳入的offset和pageSize分別為8和20。各分表中符合條件的數量分別為10,10,50。那麽我們需要將總的分頁條件轉化為三個分表各自的分頁條件,如圖

    圖片

    透過上圖可以看到,大分頁條件(offset=8,pageSize=20),轉換為(offset=8,pageSize=2),(offset=0.pageSize=10),(offset=0,pageSize=8)三個條件。

    整個計算過程如下:

    1. 多執行緒查詢各個分表中滿足條件的數據數量

    2. 將各個表數量按照分表的先後順序累加,形成圖 8的數軸

    3. 判斷第一條數據和最後一條數據所在的表

    4. 除第一條和最後一條數據所在表外,其他表offset=0,pageSize=總數量

    5. 計算第一條數據的offset,pageSize

    計算最後一條數據的pageSize,同時將該表查詢條件的offset設定為0

    數據遷移方案

    在數據遷移前,團隊討論過兩套遷移方案:

    1)請DBA遷移數據;

    2)手寫程式碼遷移數據,他們各有自己的優缺點:

    圖片

    綜合考慮時間成本和對線上資料庫的影響,團隊決定采用兩種方案結合的方式:

  • 交易時間為三個月前的冷數據,由於更新機率不大,采用程式碼的方式遷移,人為控制每次遷移數量,少量多次,螞蟻搬家;

  • 交易時間為三個月內的熱數據,由於會在上線前頻繁出現更新操作,則在上線前停止寫操作,而後由DBA整體遷移。這樣將時間成本平攤到平時,上線前只有約2個小時左右遷移數據時系統無法使用。

  • 同時,除了最後一次DBA遷移數據外,能夠人為控制每次遷移的數據量,整體避免資料庫例項級別的高延遲。

  • 整體上線流程

    為保證新表拆分功能的穩定性和大表下線的穩定,團隊將整個計畫分為三個階段:

  • 第一階段: 建立分表,大表數據遷移分表,線上數據新表老表雙寫,所有查詢走分表(驗證觀察)

  • 第二階段: 停止寫老數據表,其他業務直連資料庫改為資金提供對外介面(驗證觀察)

  • 第三階段 :大表下線

  • 總結

  • 應再進一步調研分表相關中介軟體。由於計畫分表依據的特殊性,導致sharding-jdbc的很多功能無法利用,其對於簡化查詢邏輯的幫助低於預期。並且sharding-jdbc獨立資料來源的特性,引發了多資料來源事務問題,反而增加了開發的工作量。

  • 多執行緒需要仔細分析執行緒池核心執行緒的大小,同分時析多執行緒池同時存在的時候是否會引起核心執行緒數過多,避免機器執行緒打滿。

  • 如果是一個已有的計畫,在進行分表改造時,一定要將各種場景都羅列清楚,將各個場景細化到程式中的每個類、每個方法中,將所有業務場景都覆蓋到。

  • 在遷移歷史數據時,一定要做好遷移數據方案,以及應對出現數據不一致時的處理方案。要綜合考慮時間成本、數據準確性、對線上功能的影響等諸多因素。

  • 在上線一個比較復雜的方案時,一定要提前設計好回滾方案和降級措施,能夠極大保證穩定性。

  • 說點兒題外話

    為啥說想說點兒題外話呢,主要是對這次延續了5個多月的計畫有感而發。計畫進行過程中,難免會與其他系統的維護團隊有工作上的交集,有需要其他團隊配合的地方。

    這個時候非常考驗程式設計師的溝通能力,最優秀的程式設計師能夠透過話術把對方拉到自己的陣線當中,讓對方感到這項工作對自己也是有好處的。這樣能夠讓對方心甘情願的配合你的工作,達到雙贏的目的。

    如果程式設計和學習能力是程式設計師的硬實力,那溝通技巧就是程式設計師的軟實力,硬實力能夠保障你的下線,而決定上線的恰恰是軟實力。

    因此很多程式設計師不註重溝通技巧的培養,其實是相當於瘸腿的,畢竟現在憑單打獨鬥是不大可能做出事情的。

    另外,至少對於我們單位來說,對後端程式設計師的綜合素質其實要求最高。後端程式設計師集業務、技術於一身。需要有比較強的業務把控能力,還要有過硬的技術素質。

    同時,大多數工作的主owner是後端,一般都是後端程式設計師把控前端、後端、QA的開發節奏,協調好各個時間點,做好風險反饋。

    這就要求後端程式設計師既要懂業務,還要懂技術,還需要有一定的管理能力。這其實對人的鍛煉還是很可觀的。

    👉 歡迎 ,你將獲得: 專屬的計畫實戰 / Java 學習路線 / 一對一提問 / 學習打卡 / 每月贈書

    新計畫: 仿小紅書 (微服務架構)正在更新中... , 全棧前後端分離部落格計畫 2.0 版本完結啦, 演示連結 http://116.62.199.48/ 。全程手摸手,後端 + 前端全棧開發,從 0 到 1 講解每個功能點開發步驟,1v1 答疑,直到計畫上線。 目前已更新了261小節,累計41w+字,講解圖:1806張,還在持續爆肝中.. 後續還會上新更多計畫,目標是將Java領域典型的計畫都整一波,如秒殺系統, 線上商城, IM即時通訊,Spring Cloud Alibaba 等等,


    1. 

    2. 

    3. 

    4. 

    最近面試BAT,整理一份面試資料Java面試BATJ通關手冊,覆蓋了Java核心技術、JVM、Java並行、SSM、微服務、資料庫、數據結構等等。

    獲取方式:點「在看」,關註公眾號並回復 Java 領取,更多內容陸續奉上。

    PS:因公眾號平台更改了推播規則,如果不想錯過內容,記得讀完點一下在看,加個星標,這樣每次新文章推播才會第一時間出現在你的訂閱列表裏。

    「在看」支持小哈呀,謝謝啦