1. 程式人生 > >100億資料平滑資料遷移,不影響服務

100億資料平滑資料遷移,不影響服務

一、問題的提出

網際網路有很多“資料量較大,併發量較大,業務複雜度較高”的業務場景,其典型系統分層架構如下:


1)上游是業務層biz,實現個性化的業務邏輯

2)中游是服務層service,封裝資料訪問

3)下游是資料層db,儲存固化的業務資料

服務化分層架構的好處是,服務層遮蔽下游資料層的複雜性,例如快取、分庫分表、儲存引擎等儲存細節不需要向呼叫方暴露,而只向上遊提供方便的RPC訪問介面,當有一些資料層變化的時候,所有的呼叫方也不需要升級,只需要服務層升級即可。

網際網路架構,很多時候面臨著這樣一些需求:


需求1->底層表結構變更:資料量非常大的情況下,資料表增加了一些屬性,刪除了一些屬性,修改了一些屬性。



需求2->分庫個數變換:由於資料量的持續增加,底層分庫個數非成倍增加。


需求3->底層儲存介質變換:底層儲存引擎由一個數據庫換為另一個數據庫。

種種需求,都需要進行資料遷移,如何平滑遷移資料,遷移過程不停機,保證系統持續服務,是文字將要討論的問題

二、停機方案

在討論平滑遷移資料方案之前,先看下不平滑的停機資料遷移方案,主要分三個步驟。


步驟一一個類似“為了給廣大使用者提供更好的服務,伺服器會在凌晨0:00-0:400進行停機維護”的公告,並在對應時段進行停機,這個時段系統沒有流量進入。


步驟二:停機後,研發一個離線的資料遷移工具,進行資料遷移。針對第一節的三類需求,會分別開發不同的資料遷移工具。

1)底層表結構變更需求:開發舊錶導新表的工具

2)分庫個數變換需求:開發2庫導3庫的工具

3)底層儲存介質變換需求:開發MongoMysql工具



步驟三恢復服務,並將流量切到新庫,不同的需求,可能會涉及不同服務升級。

1)底層表結構變更需求:服務要升級到訪問新表

2)分庫個數變換需求:服務不需要升級,只需要改尋庫路由配置

3)底層儲存介質變換需求:服務升級到訪問新的儲存介質

總的來說,停機方案是相對直觀和簡單的,但對服務的可用性有影響,許多遊戲公司的伺服器升級,遊戲分割槽與合區,可能會採用類似的方案。

除了影響服務的可用性,這個方案還有一個缺點,就是必須在指定時間完成升級

,這個對研發、測試、運維同學來說,壓力會非常大,一旦出現問題例如資料不一致,必須在規定時間內解決,否則只能回滾。根據經驗,人壓力越大越容易出錯,這個缺點一定程度上是致命的。

無論如何,停機方案並不是今天要討論的重點,接下來看一下常見的平滑資料遷移方案

三、平滑遷移-追日誌法

平滑遷移方案一,追日誌法,這個方案主要分為五個步驟。


資料遷移前,上游業務應用通過舊的服務訪問舊的資料。


步驟一:服務進行升級,記錄“對舊庫上的資料修改”的日誌(這裡的修改,為資料的insertdeleteupdate),這個日誌不需要記錄詳細資料,主要記錄:

1)被修改的庫

2)被修改的表

3)被修改的唯一主鍵

具體新增了什麼行,修改後的資料格式是什麼,不需要詳細記錄。這樣的好處是,不管業務細節如何變化,日誌的格式是固定的,這樣能保證方案的通用性。

這個服務升級風險較小:

1)寫介面是少數介面,改動點較少

2)升級只是增加了一些日誌,對業務功能沒有任何影響


步驟二研發一個數據遷移工具,進行資料遷移。這個資料遷移工具和離線遷移工具一樣,把舊庫中的資料轉移到新庫中來。

這個小工具的風險較小:

1)整個過程依然是舊庫對線上提供服務

2)小工具的複雜度較低

3)任何時間發現問題,都可以把新庫中的資料幹掉重來

4)可以限速慢慢遷移,技術同學沒有時間壓力

資料遷移完成之後,就能夠切到新庫提供服務了麼?

答案是否定的,在資料遷移的過程中,舊庫依然對線上提供著服務,庫中的資料隨時可能變化,這個變化並沒有反映到新庫中來,於是舊庫和新庫的資料並不一致,所以不能直接切庫,需要將資料追平。

哪些資料發生了變化呢?

步驟一中日誌裡記錄的不就是麼?


步驟三研發一個讀取日誌並遷移資料的小工具,要把步驟二遷移資料過程中產生的差異資料追平。這個小工具需要做的是:

1)讀取日誌,得到哪個庫、哪個表、哪個主鍵發生了變化

2)把舊庫中對應主鍵的記錄讀取出來

3)把新庫中對應主鍵的記錄替換掉

無論如何,原則是資料以舊庫為準

這個小工具的風險也很小:

1)整個過程依然是舊庫對線上提供服務

2)小工具的複雜度較低

3)任何時間發現問題,大不了從步驟二開始重來

4)可以限速慢慢重放日誌,技術同學沒有時間壓力

日誌重放之後,就能夠切到新庫提供服務了麼?

答案依然是否定的,在日誌重放的過程中,舊庫中又可能有資料發生了變化,導致資料不一致,所以還是不能切庫,需要進一步讀取日誌,追平記錄。可以看到,重放日誌追平資料的程式是一個while(1)的程式,新庫與舊庫中的資料追平也會是一個“無限逼近”的過程

什麼時候資料會完全一致呢?



步驟四:在持續重放日誌,追平資料的過程中,研發一個數據校驗的小工具,將舊庫和新庫中的資料進行比對,直到資料完全一致

這個小工具的風險依舊很小:

1)整個過程依然是舊庫對線上提供服務

2)小工具的複雜度較低

3)任何時間發現問題,大不了從步驟二開始重來

4)可以限速慢慢比對資料,技術同學沒有時間壓力


步驟五:在資料比對完全一致之後,將流量遷移到新庫,新庫提供服務,完成遷移。

如果步驟四資料一直是99.9%的一致,不能完全一致,也是正常的,可以做一個秒級的舊庫readonly,等日誌重放程式完全追上資料後,再進行切庫切流量。

至此,升級完畢,整個過程能夠持續對線上提供服務,不影響服務的可用性。

四、平滑遷移-雙寫法

平滑遷移方案二,雙寫法,這個方案主要分為四個步驟。


資料遷移前,上游業務應用通過舊的服務訪問舊的資料。


步驟一服務進行升級,對“對舊庫上的資料修改”(這裡的修改,為資料的insert, deleteupdate),在新庫上進行相同的修改操作,這就是所謂的“雙寫”,主要修改操作包括:

1)舊庫與新庫的同時insert

2)舊庫與新庫的同時delete

3)舊庫與新庫的同時update

由於新庫中此時是沒有資料的,所以雙寫舊庫與新庫中的affect rows可能不一樣,不過這完全不影響業務功能,只要不切庫,依然是舊庫提供業務服務

這個服務升級風險較小:

1)寫介面是少數介面,改動點較少

2)新庫的寫操作執行成功與否,對業務功能沒有任何影響


步驟二:研發一個數據遷移工具,進行資料遷移。這個資料遷移工具在本文中已經出現第三次了,把舊庫中的資料轉移到新庫中來。

這個小工具的風險較小:

1)整個過程依然是舊庫對線上提供服務

2)小工具的複雜度較低

3)任何時間發現問題,都可以把新庫中的資料幹掉重來

4)可以限速慢慢遷移,技術同學沒有時間壓力

資料遷移完成之後,就能夠切到新庫提供服務了麼?

答案是肯定的,因為前置步驟進行了雙寫,所以理論上資料遷移完之後,新庫與舊庫的資料應該完全一致。

由於遷移資料的過程中,舊庫新庫雙寫操作在同時進行,怎麼證明資料遷移完成之後資料就完全一致了呢?



如上圖所示:

1)左側是舊庫中的資料,右側是新庫中的資料

2)按照primary keyminmax的順序,分段,限速進行資料的遷移,假設已經遷移到now這個資料段

資料遷移過程中的修改操作分別討論:

1)假設遷移過程中進行了一個insert操作,舊庫新庫都插入了資料,資料一致性沒有被破壞

2)假設遷移過程中進行了一個delete操作,這又分為兩種情況

         2.1)假設這delete的資料屬於[min,now]範圍,即已經完成遷移,則舊庫新庫都刪除了資料,資料一致性沒有被破壞

         2.2)假設這delete的資料屬於[now,max]範圍,即未完成遷移,則舊庫中刪除操作的affect rows1,新庫中刪除操作的affect rows0,但是資料遷移工具在後續資料遷移中,並不會將這條舊庫中被刪除的資料遷移到新庫中,所以資料一致性仍沒有被破壞

3)假設遷移過程中進行了一個update操作,可以認為update操作是一個delete加一個insert操作的複合操作,所以資料仍然是一致

除非除非除非,在一種非常非常非常極限的情況下:

1date-migrate-tool剛好從舊庫中將某一條資料X取出

2)在X插入到新庫中之前,舊庫與新庫中剛好X進行了雙delete操作

3date-migrate-tool再將X插入到新庫中

這樣,會出現新庫比舊庫多出一條資料X

但無論如何,為了保證資料的一致性,切庫之前,還是需要進行資料校驗的。


步驟三:在資料遷移完成之後,需要使用資料校驗的小工具,將舊庫和新庫中的資料進行比對,完全一致則符合預期,如果出現步驟二中的極限不一致情況,則以舊庫中的資料為準。

這個小工具的風險依舊很小:

1)整個過程依然是舊庫對線上提供服務

2)小工具的複雜度較低

3)任何時間發現問題,大不了從步驟二開始重來

4)可以限速慢慢比對資料,技術同學沒有時間壓力


步驟四:資料完全一致之後,將流量切到新庫,完成平滑資料遷移。

至此,升級完畢,整個過程能夠持續對線上提供服務,不影響服務的可用性。

五、總結

針對網際網路很多“資料量較大,併發量較大,業務複雜度較高”的業務場景,在

1)底層表結構變更

2)分庫個數變換

3)底層儲存介質變換

的眾多需求下,需要進行資料遷移,完成“平滑遷移資料,遷移過程不停機,保證系統持續服務”有兩種常見的解決方案。

追日誌法,五個步驟:

1服務進行升級記錄“對舊庫上的資料修改”的日誌

2)研發一個數據遷移小工具,進行資料遷移

3)研發一個讀取日誌小工具追平資料差異

4)研發一個數據比對小工具校驗資料一致性

5流量切到新庫,完成平滑遷移

雙寫法,四個步驟:

1服務進行升級,記錄“對舊庫上的資料修改”進行新庫的雙寫

2)研發一個數據遷移小工具,進行資料遷移

3)研發一個數據比對小工具校驗資料一致性

4)流量切到新庫,完成平滑遷移

文章比較長,希望大家有收穫。

幫轉喲。

==【完】==


轉自:http://mp.weixin.qq.com/s/Ozqu2A7Sy_TGKkF6yF1rDQ