隨著企業數字化的深入,系統上云或者國產化改造的需求也是越來越多,數據遷移作為其中的重點中的重點,絕對是不可繞開的一個關鍵環節。可能有人會覺得數據遷移不是很簡單嗎,用binlog把數據同步到新庫不就完了嗎?這就把問題想簡單了,事實上數據遷移架構可能會非常復雜,而且每個企業可能都面臨著不同的現狀與歷史情況。比如不是所有的系統數據庫都是MySQL,像金融等大型企業的系統早期大量使用了Oracle或其它的一些商業數據庫,甚至在某些限制的情況下DBA團隊都不提供7*24小時的主備同步的功能。這時你的架構應該怎么設計?
一般來說系統按服務對象可以分為ToC、ToB、ToG,對于后兩類系統或者規模較小的ToC類系統,通常可以有停機發布窗口,有停機窗口的系統數據遷移比無停機窗口7*24小時提供在線服務的系統相對來說會簡單不少
對于小型系統來說,系統的割接可能比較簡單,通常會在新系統中驗證通過后觀察一段時間,確認不存在回切風險后逐步下線舊系統即可。而對于大型系統來說,系統割接的時間可能持續幾個月甚至數年的時間,就像在飛行的飛機上換發動機一樣。對于高并發系統,數據的遷移除了數據庫的遷移外還需要考慮緩存的數據遷移或預熱以防止新系統在切入流量后發生緩存擊穿而雪崩。下面是一些常用的策略和對限制性條件下的思考:
最簡單的數據遷移策略
先來看一下最簡單的數據遷移策略:即可停機的一次性遷移。也就是說在停機發布窗口內,完成數據遷移并完成新環境的功能驗證測試,等恢復后用戶訪問到的系統已經更新為新系統。這種方式的優點是方案簡單,缺點是當正常提供服務時間發現新環境存在重大問題時,由于新環境的數據庫通常已經寫入了新數據,已經沒辦法切回到舊環境的舊系統,所以這種策略適用于小規模系統。
具體的做法是在停機維護開始后先在舊數據庫中執行mysqldump,再在新數據庫中導入dump文件,這種方式甚至都不要求新舊環境之間的網絡互通。在dump文件導入成功后,先進行數據驗證,通過后數據遷移工作即基本完成。再對新環境的應用程序進行功能驗證測試,通過后切換流量入口讓新環境接替舊環境對外提供服務。見下圖:
可回切的遷移策略
再來看一下稍微復雜一點的數據遷移策略:可回切的遷移策略。為了降低遷移的風險,企業通常會考慮在遷移完成并開始對外提供服務出現問題時進行回切。為了滿足回切的需求,我們通常會讓新舊兩套數據庫之間進行數據同步,新環境數據庫為主庫,舊環境數據庫為從庫,在回切時進行手工的主從倒換。這種方式也要求新舊環境間的網絡是互通的。
如上圖,剛開始,舊環境數據庫作為主庫,新環境數據庫作為從庫。為了進一步減少數據遷移的時間,可先把新環境的應用程序部署等各類工作提前做好,先不切入流量入口即可。
如上圖,在停機發布窗口到來時,先停止舊環境流量,確認主從數據庫數據同步完成后,手工執行主從倒換將舊環境數據庫轉換為從庫,新環境數據庫轉換為主庫。在對外提供服務后,由于寫入新數據庫的數據也會同步到舊數據庫,只要新舊庫之間的數據一致,舊服務就具備了回切的條件。
當發現新環境服務存在嚴重問題需要回切時,先停止新環境流量,確認數據同步完成后手工執行主從倒換并將流量入口切回舊環境。由于主從間的同步可以在數據遷移前就持續進行,真正遷移時只需要確認從庫的數據追上了主庫的數據后進行手工主從倒換,所以在這種方式也適用于很短停機窗口的系統。
雙寫的遷移策略
接下來我們來看一下更為復雜的異構數據庫遷移策略:雙寫策略。前面介紹的兩種策略都適用于同構數據庫的數據遷移,但是對于異構數據庫之間的數據遷移,我們應該如何設計呢?畢竟國產化改造多數情況是從一些商業數據庫往國產或開源的數據庫上進行遷移居多。
有一些商業的異構數據遷移工具號稱可以支持7*24小時的異構數據庫同步,但由于不同商業數據庫擁有各自豐富的特性,很難覆蓋所有方面。因此,我認為可以使用這類商業工具來進行存量數據的輔助遷移和驗證,但對于實時產生的增量數據,主要還是依靠應用程序的雙寫機制來處理。
關于雙寫的實現方法,有多種選擇,每種方法都有其優缺點和適用環境。根據增量數據的來源不同,主要有增量日志訂閱方案和應用層雙寫方案。
增量日志訂閱方案中,最常見的是使用開源工具Canal來訂閱主庫的Mysql binlog變化,并消費binlog以獲取增量數據。這種方式只適用于Mysql作為源數據庫的情況。雖然也有一些方案可以支持Oracle等商業數據庫的數據遷移,例如愚公等工具,但它們需要額外的物化視圖權限,并且可能對性能產生影響,實際應用中使用時會有一定限制。
應用層雙寫方案包括應用同步雙寫和異步雙寫兩種方式。應用同步雙寫是指應用程序同時連接兩個數據源,在寫入數據時同時向兩個數據庫中寫入數據。這種方式會在一定程度上降低應用程序的性能,因為現在需要同時插入兩個庫,而不僅僅是一個庫。此外,該方式還要求應用與兩個數據庫必須在相同機房或者同一可用區,否則跨網絡導致的時間開銷會大大增加。應用異步雙寫方案與同步雙寫的不同之處在于,第二個庫的寫入是異步進行的。可以通過使用消息隊列的方式來實現這種異步操作。由于采用了異步雙寫,對應用程序的性能影響非常小。
異步雙寫方案的具體實現如上圖所示。在這種方案中,應用在寫入數據時同時將數據寫入消息隊列。為了確保單個表的時序正確性,可以為每個表配置一個獨立的消費者來處理消息隊列中的數據。此外,為了進一步保證數據的一致性,還需要設計一個基于增量行的檢查程序,該程序依賴于源表中的last_update_time字段,用于確保兩個數據庫之間的數據一致性。
對于換數據庫與上云同時存在的需求,其實應該考慮分步去實施,即先完成一項再完成另一項,這樣在上云的過程中可以利用同構數據庫的主從同步方案,在換數據庫過程中不需要考慮跨機房網絡損耗問題帶來的各種限制。
迭代的遷移策略
在實際情況中,數據遷移可能需要采取迭代進行的策略。例如,在云原生重構方案中,企業可以安排一部分人員對系統進行重構,同時讓另一部分人員繼續在舊系統中進行需求的迭代開發。支持迭代遷移的基礎是前端能夠靈活地支持路由策略,即前端可以同時將部分服務路由到新環境,將其他服務路由到舊環境中。前端需要支持路由策略設計見下圖:
與異構數據庫遷移策略相比,迭代遷移策略需要持續的周期。這種策略通常伴隨著系統的重構,并且一般按照模塊進行。為了更好地實施迭代遷移,對每個模塊的遷移甚至可以將遷移過程分為兩個步驟:非實時讀業務的遷移和實時讀寫業務的遷移。
緩存的數據遷移策略
在進行緩存遷移時,一般不會直接遷移緩存數據,但需要考慮緩存的預熱。對于中小規模的系統,也可以直接丟棄緩存數據,讓新環境的系統在運行過程中逐漸生成新的緩存。然而,在高并發環境下,為了防止新環境系統在接收流量后發生緩存擊穿并導致雪崩效應,我們需要進行緩存的預熱。為了使預熱的數據更符合實際情況,我們可以將舊環境中一定比例的寫入緩存操作異步同步給新環境的緩存服務器,從而實現預熱的效果。由于新緩存的更新是異步的且按比例進行,對系統性能的影響很小。
如上圖,當舊環境的緩存服務發生更新時,異步地刷新環境緩存服務器的內容,這樣新環境緩存服務器的數據就根據實際的數據分布提前完成了預熱。