記一次數據庫冷熱分離

前言

最近在一家小公司實習,文章也沒怎麼更新。前兩天參與了後臺系統數據庫冷熱分離(一期)的工做,雖然只是參與了定時任務和接口的開發改造,但仍是想了解一下它的來龍去脈,畢竟做爲一隻鹹魚,就要有翻身以後再做鹹魚的覺悟,因而就有了這篇文章。html

先說一下背景吧,隨着業務的發展,生產庫中訂單等數據已經有數千萬,而相似訂單詳情、結算詳情的數據則已通過億,而且天天以 20w+ 的數據在增長,能夠說對數據庫的改造已是迫在眉睫了。前端

解決方案

考慮到具體的業務須要,按照用戶的習慣,通常在近期的訂單、訂單詳情等數據,因爲有待評價、售後等問題,訪問會比較多,這些數據就稱之爲熱數據;數據庫

而對於較早時間的訂單、訂單詳情等數據,通常都是已評價、已完成售後等狀態,用戶通常不會常常訪問,這些數據就稱之爲冷數據。分佈式

因此考慮是否可以進行冷熱分離。對於須要常常查詢的數據放在生產庫中,例如一個月以內的數據;而那些查詢很少的數據,例如一個月以前的數據,將其遷移到歷史庫中。這樣既能夠減輕生產庫的壓力,也能夠保持數據的完整。性能

如何遷移

定好大體方案後,就要考慮如何對數據進行遷移了。因爲數據量過大,遷移不可能一次並在短期內就完成。學習

對於之前的數據,考慮在凌晨分批次進行遷移。因爲不一樣時期的數據量不一樣,定時任務很差實現,只能經過手動查詢,可能剛開始是好幾個月的數據一塊兒遷移,到後面就是十幾天的數據一塊兒遷移。測試

這裏經過人工去判斷一段時間內的數據量,並進行遷移,主要就是爲了保證遷移工做不能影響生產庫的正常運行,另外也要讓遷移次數較少,遷移工做盡早完成。設計

而對於之後的增量數據,則能夠設置定時任務,每日凌晨自動執行,遷移一個月以前的數據。cdn

在遷移數據時,以訂單爲粒度進行遷移,其總體的邏輯主要分爲如下幾步:htm

  • 數據遷移工做:
    • 每次查詢一部分數據(例如 500 條/1000條),判斷其是否已經遷移過(額外一張表記錄遷移狀態),這主要是爲了防止一次查詢過多數據會影響生產庫的運行;
    • 若是沒有遷移過,則查詢與該訂單相關的數據,將其遷移到新庫中,並更新遷移狀態;
  • 測試檢驗工做:
  • 主庫刪除工做:在測試一段時間後,若是無誤,則將主庫中的已經遷移完成的數據刪除,一樣這裏每次刪除一部分數據。

讀寫設計

在數據遷移後,另外一個問題就是如何讀寫了,通常會有以下幾種方案。

對於讀操做,一種方案是,每次在查詢時,優先查詢熱庫,只有當結果沒有命中,或只有部分命中時,纔去查詢冷庫。這裏爲了區分所有命中和部分命中,能夠在熱庫中建立一個表,記錄每次要求查詢冷庫時的查詢條件、查詢的結果數量等。在查詢熱庫時,若是相同查詢條件的查詢結果數量一致,則本地查詢結束,不然就要到冷庫中進行查詢。

另外一種方案,則能夠經過前端配合實現,每次查詢時,默認只查詢最近一段時間內的數據,也就是主庫內的數據。若是用戶須要查詢之前的數據時,再去冷庫中查詢就行了。這也是目前我司的實現方案。

而對於寫操做,也有兩種方案。

一種是每次在存儲數據時,在熱庫中存儲一份,在冷庫歷史表中一樣存儲一份。而後每日凌晨經過定時任務刪除一段時間以前的數據,若是數據量較大的話,能夠按照區間進行刪除,防止影響生產庫的正常運行。

另外一種方案,與之相似,只不過在寫操做時,只是在熱庫中進行存儲。將數據從熱庫遷移到冷庫的操做,放在凌晨的定時任務中執行。

擴展學習

其實通常來講,單表數據量在數千萬時,數據的寫入和查詢效率就會受到影響。這時就應該考慮進行分表,例如水平分表、垂直分表。

分表

對於水平分表,也有多種分表的策略。

按照範圍劃分

按照範圍劃分,例如將表中的數據按照時間,每月或每一個季度一張表。

這種作法也有利有弊:

  • 好處是能夠很容易來控制單表的大小,自然擴展,數據量很大時只須要減少時間的粒度便可;
  • 缺點是對批量寫入等操做的效率問題沒有解決,仍是集中在一種表上。

按照 Hash 切分

按照 Hash 切分,通常使用 Mod 2^n 將數據劃分到不一樣的表中。

mod 的值選擇爲 2^n,具體根據業務決定,目標就是爲了在之後的擴展時能儘可能少遷移,甚至不遷移數據。

這種作法若是劃分均勻,批量寫入、查詢等操做均攤到各個表中,對性能不會有太大影響。可是須要對 mod 的值仔細權衡,方便之後的擴展。

分庫

分表很大程度上解決了單表寫入和查詢的效率,但對於數據庫而言,其負載壓力並無變化,對於分庫也有相似於分表的不少策略,這裏就再也不多說了。

最後

分庫分表雖然帶來了很大的好處,但也有一些問題須要處理,除了讀寫設計外,還有分佈式 id,分佈式事務,動態擴容等問題等着咱們一個一個去挑戰。活到老,學到老。

參考資料

相關文章
相關標籤/搜索