爲什麼要分庫分表,分庫分表的實踐請看之前的文章:微服務-分庫分表思路
分庫分表之前我們首先要選出分片字段、然後根據一定的分片算法將數據寫入不同的庫表,查詢數據的時候根據分片字段+分片算法從對應的庫表中拿取數據即可
因此,由單獨進行橫向拆分後需要將老數據按照我們定義的,分片字段和分片算法重新洗數據,那麼我們本節主要講解3中方法:停機數據遷移、新老庫雙寫、寫老庫通過binlog同步新庫
一、上線前停服數據遷移
實踐思路:
- 新建線上新庫(按照分片鍵+分片算法新建)
- 編寫數據同步程序(查詢老庫,然後按照分片算法遷移到新庫)
- 在數據訪問最少的時間段(比如半夜2點)停服務、開始跑我們的同步程序
- 數據同步完成後(要進行數據一致性校驗,比如校驗總數)上新代碼,連接新庫
優點:
- 數據一致性能得到保障
- 簡單,沒什麼技術含量
缺點:
- 需要停服務(如果不停服務可能導致已經同步的數據在同步過程中有變更,導致數據不一致)
- 數據同步時間較長,出錯率高
- 熬夜
題外話:最後一步一定要做數據校驗,如果停服務的話一般校驗數據總條數即可,如果同步過程中出現錯誤,一定要記錄,否則數據矯正略麻煩;如果真的出現數據不一致的情況,提供一直校驗思路:
同樣的查詢條件分表查詢新老庫,分別MD5,然後做對比
二、新老庫雙寫
上一種爲什麼要停服務:就是怕在遷移過程中,有數據修改出現數據不一致的情況,那麼爲了解決數據不一致的情況我們可以在遷移過程中寫的數據,同時寫入新老庫
流程解釋:
- 新建線上新庫(按照分片鍵+分片算法新建)
- 修改源碼,將之前代碼新增、修改、刪除的地方都修改成同時寫新老庫
- 寫入數據庫中間件之前先判斷新庫中是否有此次操作的數據
- 新增操作:如果新庫無數據:直接新增,如果有數據:直接丟棄
- 修改操作:如果新庫有數據:確保新數據覆蓋舊數據,如果無數據:直接丟棄
- 刪除操作:如果新庫有數據:直接刪除,如果無數據:直接丟棄
- 啓動後臺數據遷移程序
- 查詢老庫,查出數據後通過新庫規則查詢新庫,如果無數據直接寫入,如果有數據比較時間戳,確保新數據覆蓋舊數據,如果是老數據想覆蓋新數據,直接丟棄
- 數據遷移完畢後,進行數據校驗
- 修改源碼,將之前同時寫新老庫的地方全部改成只寫新庫
- 經過一段時間,無異常後下掉老庫和遷移工具
優點:
- 對用戶而言無感知,不需要停服務
- 有充足的時間檢驗數據的準確性(切新庫之前所有用戶操作都走的老庫)
- 不用熬夜
缺點:
- 代碼侵入,需要修改兩次源碼,容易漏
總結:上種方法需要很多的判斷,判斷新庫中是否有數據,如果有怎麼處理,如果沒有怎麼處理,牽扯到了一些邏輯,因此我們有沒有一種辦法不用判斷
第二種優化策略
解釋:
- 新建線上新庫(按照分片鍵+分片算法新建)
- 啓動後臺數據遷移程序,只遷移指定時間以後的歷史數據
- 修改源碼,將之前代碼新增、修改、刪除的地方都修改成同時寫老庫可放入消息隊列
- 歷史數據遷移完畢校驗通過後,遷移程序開始監聽消息隊列,將擠壓消息寫入到新庫
- 當新老庫數據校驗通過,切到讀寫新庫
總體思路:先遷移老數據,然後消費新數據,不需要各種邏輯判斷
當然缺點還是沒有避免,還是要修改源碼,有沒有不修改源碼的呢,,,
三、讀寫老庫,通過老庫binlog同步新庫
解釋:
- 將老庫binlog開啓row level模式下
- 新建線上新庫(按照分片鍵+分片算法新建)
- 啓動後臺數據遷移程序,只遷移指定時間以後的歷史數據
- 歷史數據遷移完畢校驗通過後,遷移程序開始監聽binlog的增刪改事件,將消息寫入到新庫
- 當新老庫數據校驗通過,切到讀寫新庫
題外話:監聽binlog增刪改事件可以用阿里的canal
公衆號主要記錄各種源碼、面試題、微服務技術棧,幫忙關注一波,非常感謝