最近在一家小公司實習,文章也沒怎麼更新。前兩天參與了後臺系統數據庫冷熱分離(一期)的工做,雖然只是參與了定時任務和接口的開發改造,但仍是想了解一下它的來龍去脈,畢竟做爲一隻鹹魚,就要有翻身以後再做鹹魚的覺悟,因而就有了這篇文章。html
先說一下背景吧,隨着業務的發展,生產庫中訂單等數據已經有數千萬,而相似訂單詳情、結算詳情的數據則已通過億,而且天天以 20w+ 的數據在增長,能夠說對數據庫的改造已是迫在眉睫了。前端
考慮到具體的業務須要,按照用戶的習慣,通常在近期的訂單、訂單詳情等數據,因爲有待評價、售後等問題,訪問會比較多,這些數據就稱之爲熱數據;數據庫
而對於較早時間的訂單、訂單詳情等數據,通常都是已評價、已完成售後等狀態,用戶通常不會常常訪問,這些數據就稱之爲冷數據。分佈式
因此考慮是否可以進行冷熱分離。對於須要常常查詢的數據放在生產庫中,例如一個月以內的數據;而那些查詢很少的數據,例如一個月以前的數據,將其遷移到歷史庫中。這樣既能夠減輕生產庫的壓力,也能夠保持數據的完整。性能
定好大體方案後,就要考慮如何對數據進行遷移了。因爲數據量過大,遷移不可能一次並在短期內就完成。學習
對於之前的數據,考慮在凌晨分批次進行遷移。因爲不一樣時期的數據量不一樣,定時任務很差實現,只能經過手動查詢,可能剛開始是好幾個月的數據一塊兒遷移,到後面就是十幾天的數據一塊兒遷移。測試
這裏經過人工去判斷一段時間內的數據量,並進行遷移,主要就是爲了保證遷移工做不能影響生產庫的正常運行,另外也要讓遷移次數較少,遷移工做盡早完成。設計
而對於之後的增量數據,則能夠設置定時任務,每日凌晨自動執行,遷移一個月以前的數據。cdn
在遷移數據時,以訂單爲粒度進行遷移,其總體的邏輯主要分爲如下幾步:htm
在數據遷移後,另外一個問題就是如何讀寫了,通常會有以下幾種方案。
對於讀操做,一種方案是,每次在查詢時,優先查詢熱庫,只有當結果沒有命中,或只有部分命中時,纔去查詢冷庫。這裏爲了區分所有命中和部分命中,能夠在熱庫中建立一個表,記錄每次要求查詢冷庫時的查詢條件、查詢的結果數量等。在查詢熱庫時,若是相同查詢條件的查詢結果數量一致,則本地查詢結束,不然就要到冷庫中進行查詢。
另外一種方案,則能夠經過前端配合實現,每次查詢時,默認只查詢最近一段時間內的數據,也就是主庫內的數據。若是用戶須要查詢之前的數據時,再去冷庫中查詢就行了。這也是目前我司的實現方案。
而對於寫操做,也有兩種方案。
一種是每次在存儲數據時,在熱庫中存儲一份,在冷庫歷史表中一樣存儲一份。而後每日凌晨經過定時任務刪除一段時間以前的數據,若是數據量較大的話,能夠按照區間進行刪除,防止影響生產庫的正常運行。
另外一種方案,與之相似,只不過在寫操做時,只是在熱庫中進行存儲。將數據從熱庫遷移到冷庫的操做,放在凌晨的定時任務中執行。
其實通常來講,單表數據量在數千萬時,數據的寫入和查詢效率就會受到影響。這時就應該考慮進行分表,例如水平分表、垂直分表。
分表
對於水平分表,也有多種分表的策略。
按照範圍劃分
按照範圍劃分,例如將表中的數據按照時間,每月或每一個季度一張表。
這種作法也有利有弊:
按照 Hash 切分
按照 Hash 切分,通常使用 Mod 2^n 將數據劃分到不一樣的表中。
mod 的值選擇爲 2^n,具體根據業務決定,目標就是爲了在之後的擴展時能儘可能少遷移,甚至不遷移數據。
這種作法若是劃分均勻,批量寫入、查詢等操做均攤到各個表中,對性能不會有太大影響。可是須要對 mod 的值仔細權衡,方便之後的擴展。
分庫
分表很大程度上解決了單表寫入和查詢的效率,但對於數據庫而言,其負載壓力並無變化,對於分庫也有相似於分表的不少策略,這裏就再也不多說了。
分庫分表雖然帶來了很大的好處,但也有一些問題須要處理,除了讀寫設計外,還有分佈式 id,分佈式事務,動態擴容等問題等着咱們一個一個去挑戰。活到老,學到老。