???????隨著業(yè)務(wù)的發(fā)展,應(yīng)用系統(tǒng)要提前做好數(shù)據(jù)存儲規(guī)劃,及時應(yīng)對海量數(shù)據(jù)創(chuàng)建和訪問壓力。這篇文章根據(jù)工作中的業(yè)務(wù)場景總結(jié)了如何實現(xiàn)大數(shù)據(jù)表優(yōu)化方案。下面先列出應(yīng)用場景:
- 數(shù)據(jù)庫:mysql
- 應(yīng)用服務(wù):訂單服務(wù)
- 業(yè)務(wù)要求:依賴訂單的其它服務(wù)不做調(diào)整,不影響線上訂單交易
讀寫分離
???????實際業(yè)務(wù)中,圍繞著訂單的服務(wù)非常多:營銷,售后,清結(jié)算等等,訂單查詢請求占比遠(yuǎn)大于并發(fā)寫的請求。因此數(shù)據(jù)庫采用主從復(fù)制架構(gòu),查詢請求通過從庫獲取數(shù)據(jù)。在應(yīng)用層面,訂單查詢作為一個單獨的系統(tǒng)對外提供查詢服務(wù),具體到編碼層面使用開源的sharding-jdbc作為主從數(shù)據(jù)庫訪問分離。
讀寫分離方案,減少主庫訪問壓力。但是數(shù)據(jù)庫主從復(fù)制保證最終一致性,存在延遲的問題。因此針對實時性要求較高的查詢,需要從主庫獲取數(shù)據(jù)。
訂單遷移
???????實際業(yè)務(wù)中,訂單單表已經(jīng)接近億級。對表進(jìn)行DDL操作影響在線交易,增加主從復(fù)制延遲等。由于訂單交易生命周期較短,這里交易生命周期指的是狀態(tài)的變化,如下圖:

???????普通訂單3天結(jié)束,如果參與預(yù)售,拼團(tuán)等營銷活動,最長不超過2個月。超過訂單交易生命周期的訂單不會進(jìn)行寫操作。因此定義60天前的訂單作為歷史訂單,并通過定時任務(wù)遷移歷史訂單到歷史數(shù)據(jù)庫。
通過遷移數(shù)據(jù),保證主庫(活動庫)訂單表的數(shù)據(jù)級在千萬左右。
歷史訂單水平分表
???????雖然經(jīng)過數(shù)據(jù)遷移,保證了主庫(活動庫)單表數(shù)據(jù)量減少的問題,但是歷吏訂單表數(shù)據(jù)仍然接近億級。這時采用水平分表方案,具體規(guī)則如下:
- 根據(jù)訂單號所在區(qū)間,存儲到指定的數(shù)據(jù)庫的指定表
- 訂單相關(guān)的子表,存儲到與訂單主表有相同的表后綴的子表
- 啟動定時任務(wù),根據(jù)上面的規(guī)則把主庫中的歷史訂單遷移到歷史庫中對應(yīng)的子表。
通過水平分表,減少單表數(shù)據(jù)量
搜索引擎
???????由于歷史訂單采用了水平分表方案,并且僅按照訂單號進(jìn)行路由,對于非訂單號的查詢請求(例如用戶名,商品名稱等,下單時間等)必須便利所有的子表,影響查詢性能。因此引入搜索引擎ElstaticSearch,它提供非訂單號的查詢請求,返回訂單號,然后再根據(jù)訂單號從相應(yīng)的表中查詢需要的詳情信息。具體實施步驟如下:
- 統(tǒng)計查詢訂單的所有接口使用的查詢條件
- 整理成Json結(jié)構(gòu)(盡量采用扁平結(jié)構(gòu))
- 提供訂單全量查詢接口,返回第2步整理的json數(shù)據(jù),此接口用于全量創(chuàng)建ES訂單索引。(索引重建時也會用到)
- 啟動定時任務(wù),把動態(tài)遷移的歷史訂單同步創(chuàng)建ES訂單索引。
- 創(chuàng)建ES索引成功后記錄此訂單號(在查詢時使用)
- 刪除主庫中相應(yīng)的訂單記錄。
引入搜索引擎,解決非訂單號查詢問題
分頁查詢
???????分頁需求通常包下面幾個數(shù)據(jù):每頁個數(shù),總條數(shù),總頁數(shù),當(dāng)前頁。經(jīng)過上面的改造,訂單數(shù)據(jù)已經(jīng)拆分到3個地方:活動庫,歷史庫和搜索引擎(對歷史庫創(chuàng)建的索引)。具體查詢規(guī)則如下:
- 根據(jù)查詢條件,查詢活動庫滿足條件的總數(shù)
- 根據(jù)查詢條件,查詢搜索引擎滿足查詢條件的總數(shù)
- 根據(jù)當(dāng)前請求頁碼及每頁請求數(shù)量,計算需要返回的條數(shù)。
- 根據(jù)上面3步判斷請求數(shù)據(jù)是在全部在活動庫或者歷史庫,還是部分在活動庫部分在歷史庫。此步操作可以抽象為兩個有序集合分頁算法。
- 根據(jù)第4步的結(jié)果從相應(yīng)的地方獲取需要的訂單數(shù)據(jù)返回。
由于遷移的訂單并沒有及時從數(shù)據(jù)庫刪除,也沒有及時創(chuàng)建ES索引,因此在1,2步查詢時需要把最后一次在ES中創(chuàng)建索引的訂單號做為查詢活動庫和歷史庫的臨界值
全量備份
???????在實際業(yè)務(wù)中,有些部門會直接依賴訂單數(shù)據(jù)庫,訂單數(shù)據(jù)遷移影響很大。因此提出全量備份方案,利用開源框架otter進(jìn)行訂單數(shù)據(jù)的準(zhǔn)實時備份。由于歷史訂單會從活動庫中刪除,需要修改otter框架,過濾刪除操作。
通過此方案,保證有全量數(shù)據(jù)庫的存在,即作為一個備份,也可給其它部門直接使用。
檢查任務(wù)
???????在數(shù)據(jù)的遷移過程中,難免會出現(xiàn)數(shù)據(jù)不一致的問題,比如活動庫與歷史庫數(shù)據(jù)不一致,歷史庫與ES數(shù)據(jù)不一致。因此部署對應(yīng)的檢查任務(wù),定時檢查數(shù)據(jù)一致性。
???????整個解決方案,僅需要修改訂單查詢服務(wù)。依賴訂單服務(wù)的其它服務(wù)不需要改動,同時對產(chǎn)線交易系統(tǒng)沒有影響。