前言
筆者是在兩年前接手公司的財務系統(tǒng)的開發(fā)和維護工作。在系統(tǒng)移交的初期,筆者和團隊就發(fā)現(xiàn),系統(tǒng)內有一張5000W+的大表。
跟蹤代碼發(fā)現(xiàn),該表是用于存儲資金流水的表格,關聯(lián)著眾多功能點,同時也有眾多的下游系統(tǒng)在使用這張表的數(shù)據(jù)。
進一步的觀察發(fā)現(xiàn),這張表還在以每月600W+的數(shù)據(jù)持續(xù)增長,也就是說,不超過半年,這張表會增長到1個億!
這個數(shù)據(jù)量,對于mysql數(shù)據(jù)庫來說是絕對無法繼續(xù)維護的了,因此在接手系統(tǒng)兩個月后,我們便開起了大表拆分的專項工作。(兩個月時間實際上主要用來熟悉系統(tǒng)、消化堆積需求了)
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
拆表前系統(tǒng)狀態(tài)
- 涉及到流水表流水的接口超時頻發(fā),部分接口基本不可用
- 每日新增流水緩慢,主要是插入數(shù)據(jù)庫的時候非常慢
- 單表占用空間過大,DBA的數(shù)據(jù)庫監(jiān)控經常報警
- 無法對表進行變更,任何alter操作都會引起主從的高延遲和長時間鎖表
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
拆表的目標
- 將流水大表數(shù)據(jù)拆分至各個分表,保證每張分表數(shù)據(jù)在1000W左右(經驗上看單表1000W的量對mysql來說沒啥壓力)
- 在拆表的前提下,針對不同接口的查詢條件進行優(yōu)化,保證各個對外、對內接口的可用性。徹底殺死m(xù)ysql慢查詢。
難點分析
- 該表的數(shù)據(jù)可以說是整個財務系統(tǒng)最基礎的數(shù)據(jù),相關功能和下游系統(tǒng)非常多。這要求開發(fā)、測試和上線流程必須極其嚴密,任何小失誤都會引起大問題。
- 涉及的場景非常多。統(tǒng)計下來,一共有26個場景,需要改造32個mapper方法,具體需要改造的方法就更加無計其數(shù)了。
- 數(shù)據(jù)量非常大,遷移數(shù)據(jù)的過程必須保證系統(tǒng)穩(wěn)定。
- 用戶較多且功能重要。分表功能上線時,必須盡量壓縮系統(tǒng)無法使用時長,同時需要保證系統(tǒng)可用性。這要求團隊必須設計完整可靠的上線流程、數(shù)據(jù)遷移方案、回滾方案、降級策略。
- 上文提到,表的拆分勢必帶來部分接口的變化,接口的變化又會帶來其他系統(tǒng)的改造。如何推動其他系統(tǒng)進行改造,如何協(xié)調多方合作的開發(fā)、測試和上線是另一個難點。
整體過程
![35ac08f6-f526-11ed-90ce-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/9A/85/wKgZomTnoziANKc_AABnri5-DME309.jpg)
具體細節(jié)
分表中間件調研
分表插件:采用sharding-jdbc作為分表插件。
其優(yōu)勢如下:
1、支持多種分片策略,自動識別=或in判斷具體在哪張分表里。
2、輕量級,作為maven依賴引入即可,對業(yè)務的侵入性極低。
為提升查詢速度,在整個項目的初期,團隊成員考慮引入ES存儲流水以提升查詢速度。
經過與ES維護團隊的兩輪討論,發(fā)現(xiàn)公司提供的ES服務對于我們的業(yè)務場景并不匹配(見表),經過反復考量,最終我們放棄了引入ES的計劃,直接從數(shù)據(jù)庫查詢數(shù)據(jù),采用每張表設置一個查詢線程的方式提升查詢效率。
![35c91ce8-f526-11ed-90ce-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9A/85/wKgZomTnoziAGpgGAADQLDCnkSs994.png)
分表依據(jù)的選擇
分表的方式有很多種,有縱向分表,有橫向分表,有分為固定的幾個表存儲然后取模進行表拆分等等??偟膩碚f,適合我們具體業(yè)務的分表方式只有橫向分表。
因為對于資金流水這種特殊數(shù)據(jù)來說,是不能清理數(shù)據(jù)的,那么縱向分表和拆成固定的幾個表都不能解決單表數(shù)據(jù)無限膨脹的問題。而橫向分表,可以把每張表的數(shù)據(jù)量恒定,到一定時間后可以進行財務數(shù)據(jù)歸檔。
分表的依據(jù)一般都是根據(jù)表的某個或者某幾個字段進行拆分,最終其實是對數(shù)據(jù)和業(yè)務分析綜合出來的結果??偟膩碚f,原則有這幾個:
- 盡可能選擇查詢條件里最常出現(xiàn)的字段,這樣能夠減少方法改造的工程
- 需要考慮根據(jù)某個字段拆分數(shù)據(jù)是否能夠均勻分布,是否能夠滿足單表1000W左右的要求
- 該字段必須是必現(xiàn)字段,不允許出現(xiàn)空值
綜合分析我們的數(shù)據(jù)以及業(yè)務需要,“交易時間”這個分表依據(jù)就呼之欲出了。
首先,這個字段作為流水最重要的字段之一一定會出現(xiàn);
第二,如果按照交易月份進行拆表,每張表大概也就是600W-700W的數(shù)據(jù);
最后,有70%的查詢都附帶“交易時間”作為查詢條件。
技術難點
多數(shù)據(jù)源事務問題
sharding-jdbc在使用的時候是需要用自己的獨立數(shù)據(jù)源的,那么就難免出現(xiàn)多數(shù)據(jù)源事務問題。
這個我們通過自定義注解,自定義切面開啟事務,通過方法棧逐層回滾or提交的方式解決的。出于保密原則,具體代碼細節(jié)不再展開。
多表的分頁問題
拆表一定會引起分頁查詢的難度增加。由于各個表查出來的數(shù)據(jù)量不等,原始的sql語句limit不再適用,需要設計一個新方法便捷的獲取分頁信息。
在此介紹一個分頁的思路供大家參考(團隊共同的成果,筆者不敢私自占有):
綜合考慮業(yè)務實際與開發(fā)的復雜程度,項目團隊決定在出現(xiàn)跨表查詢的情況下,每一張表采用一個線程進行查詢,以提高查詢效率。
這個方案的難點在于分頁規(guī)則的轉換。例如,頁面?zhèn)魅氲膐ffset和pageSize分別為8和20。各分表中符合條件的數(shù)量分別為10,10,50。那么我們需要將總的分頁條件轉化為三個分表各自的分頁條件,如圖
![35f87132-f526-11ed-90ce-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/9A/85/wKgZomTnoziAHv98AABBOZeEAmg943.jpg)
通過上圖可以看到,大分頁條件(offset=8,pageSize=20),轉換為(offset=8,pageSize=2),(offset=0.pageSize=10),(offset=0,pageSize=8)三個條件。
整個計算過程如下:
-
多線程查詢各個分表中滿足條件的數(shù)據(jù)數(shù)量
-
將各個表數(shù)量按照分表的先后順序累加,形成圖 8的數(shù)軸
-
判斷第一條數(shù)據(jù)和最后一條數(shù)據(jù)所在的表
-
除第一條和最后一條數(shù)據(jù)所在表外,其他表offset=0,pageSize=總數(shù)量
-
計算第一條數(shù)據(jù)的offset,pageSize
計算最后一條數(shù)據(jù)的pageSize,同時將該表查詢條件的offset設置為0
數(shù)據(jù)遷移方案
在數(shù)據(jù)遷移前,團隊討論過兩套遷移方案:
1)請DBA遷移數(shù)據(jù);
2)手寫代碼遷移數(shù)據(jù),他們各有自己的優(yōu)缺點:
![3611b80e-f526-11ed-90ce-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9A/85/wKgZomTnoziAb2_vAADH1SRZbjA407.png)
綜合考慮時間成本和對線上數(shù)據(jù)庫的影響,團隊決定采用兩種方案結合的方式:
- 交易時間為三個月前的冷數(shù)據(jù),由于更新幾率不大,采用代碼的方式遷移,人為控制每次遷移數(shù)量,少量多次,螞蟻搬家;
- 交易時間為三個月內的熱數(shù)據(jù),由于會在上線前頻繁出現(xiàn)更新操作,則在上線前停止寫操作,而后由DBA整體遷移。這樣將時間成本平攤到平時,上線前只有約2個小時左右遷移數(shù)據(jù)時系統(tǒng)無法使用。
- 同時,除了最后一次DBA遷移數(shù)據(jù)外,能夠人為控制每次遷移的數(shù)據(jù)量,整體避免數(shù)據(jù)庫實例級別的高延遲。
整體上線流程
為保證新表拆分功能的穩(wěn)定性和大表下線的穩(wěn)定,團隊將整個項目分為三個階段:
- 第一階段: 建立分表,大表數(shù)據(jù)遷移分表,線上數(shù)據(jù)新表老表雙寫,所有查詢走分表(驗證觀察)
- 第二階段: 停止寫老數(shù)據(jù)表,其他業(yè)務直連數(shù)據(jù)庫改為資金提供對外接口(驗證觀察)
- 第三階段:大表下線
總結
- 應再進一步調研分表相關中間件。由于項目分表依據(jù)的特殊性,導致sharding-jdbc的很多功能無法利用,其對于簡化查詢邏輯的幫助低于預期。并且sharding-jdbc獨立數(shù)據(jù)源的特性,引發(fā)了多數(shù)據(jù)源事務問題,反而增加了開發(fā)的工作量。
- 多線程需要仔細分析線程池核心線程的大小,同時分析多線程池同時存在的時候是否會引起核心線程數(shù)過多,避免機器線程打滿。
- 如果是一個已有的項目,在進行分表改造時,一定要將各種場景都羅列清楚,將各個場景細化到程序中的每個類、每個方法中,將所有業(yè)務場景都覆蓋到。
- 在遷移歷史數(shù)據(jù)時,一定要做好遷移數(shù)據(jù)方案,以及應對出現(xiàn)數(shù)據(jù)不一致時的處理方案。要綜合考慮時間成本、數(shù)據(jù)準確性、對線上功能的影響等諸多因素。
- 在上線一個比較復雜的方案時,一定要提前設計好回滾方案和降級措施,能夠極大保證穩(wěn)定性。
說點兒題外話
為啥說想說點兒題外話呢,主要是對這次延續(xù)了5個多月的項目有感而發(fā)。項目進行過程中,難免會與其他系統(tǒng)的維護團隊有工作上的交集,有需要其他團隊配合的地方。
這個時候非??简?a target="_blank">程序員的溝通能力,最優(yōu)秀的程序員能夠通過話術把對方拉到自己的陣線當中,讓對方感到這項工作對自己也是有好處的。這樣能夠讓對方心甘情愿的配合你的工作,達到雙贏的目的。
如果程序設計和學習能力是程序員的硬實力,那溝通技巧就是程序員的軟實力,硬實力能夠保障你的下線,而決定上線的恰恰是軟實力。
因此很多程序員不注重溝通技巧的培養(yǎng),其實是相當于瘸腿的,畢竟現(xiàn)在憑單打獨斗是不大可能做出事情的。
另外,至少對于我們單位來說,對后端程序員的綜合素質其實要求最高。后端程序員集業(yè)務、技術于一身。需要有比較強的業(yè)務把控能力,還要有過硬的技術素質。
同時,大多數(shù)工作的主owner是后端,一般都是后端程序員把控前端、后端、QA的開發(fā)節(jié)奏,協(xié)調好各個時間點,做好風險反饋。
這就要求后端程序員既要懂業(yè)務,還要懂技術,還需要有一定的管理能力。這其實對人的鍛煉還是很可觀的。
審核編輯 :李倩
-
數(shù)據(jù)
+關注
關注
8文章
7170瀏覽量
89705 -
數(shù)據(jù)庫
+關注
關注
7文章
3852瀏覽量
64743 -
MySQL
+關注
關注
1文章
831瀏覽量
26762
原文標題:億級別大表拆分 —— 記一次分表工作的心路歷程
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
哪里可以找到按時間表工作的例子?
解決Labview報表問題的一般思路
【睿賽德 RW007 WiFi 模塊試用連載】RW007模塊調試心路歷程
一個AVR新手藍牙模塊調試的心路歷程簡介遇到的問題
學習單片機的心路歷程分享
手機界最防水機型:蘋果8防水達IP68級別
吉利mpv國產7座大尺寸商務車,這一次做到了真正的4萬級別,官方的起售價格方面就僅需13萬元
3DMark的可變著色率測試加入Tier 2級別
元一能源從分布式光伏業(yè)務到綜合能源業(yè)務的心路歷程
黃仁勛分享作為工程師的心路歷程
一個AVR新手藍牙模塊調試的心路歷程
![<b class='flag-5'>一</b>個AVR新手藍牙模塊調試的<b class='flag-5'>心路歷程</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
記一次內網(wǎng)中反彈shell的艱難歷程
億級別大表拆分心路歷程
![<b class='flag-5'>億</b><b class='flag-5'>級別</b>大<b class='flag-5'>表</b><b class='flag-5'>拆分心路歷程</b>](https://file1.elecfans.com/web2/M00/82/D6/wKgZomRkOdKARiHlAAASqzHHSuA733.jpg)
評論