100億數(shù)據(jù)平滑數(shù)據(jù)遷移,不影響服務(wù)

2018-09-06 17:13 更新

一、問題的提出

互聯(lián)網(wǎng)有很多”數(shù)據(jù)量較大,并發(fā)量較大,業(yè)務(wù)復(fù)雜度較高”的業(yè)務(wù)場景,其典型系統(tǒng)分層架構(gòu)如下:

典型系統(tǒng)分層架構(gòu)

(1)上游是業(yè)務(wù)層biz,實現(xiàn)個性化的業(yè)務(wù)邏輯

(2)中游是服務(wù)層service,封裝數(shù)據(jù)訪問

(3)下游是數(shù)據(jù)層db,存儲固化的業(yè)務(wù)數(shù)據(jù)


服務(wù)化分層架構(gòu)的好處是,服務(wù)層屏蔽下游數(shù)據(jù)層的復(fù)雜性,例如緩存、分庫分表、存儲引擎等存儲細節(jié)不需要向調(diào)用方暴露,而只向上游提供方便的RPC訪問接口,當有一些數(shù)據(jù)層變化的時候,所有的調(diào)用方也不需要升級,只需要服務(wù)層升級即可。 

互聯(lián)網(wǎng)架構(gòu),很多時候面臨著這樣一些需求:

底層表結(jié)構(gòu)變更

需求1->底層表結(jié)構(gòu)變更:數(shù)據(jù)量非常大的情況下,數(shù)據(jù)表增加了一些屬性,刪除了一些屬性,修改了一些屬性。

分庫個數(shù)變換

需求2->分庫個數(shù)變換:由于數(shù)據(jù)量的持續(xù)增加,底層分庫個數(shù)非成倍增加。

底層存儲介質(zhì)變換

需求3->底層存儲介質(zhì)變換:底層存儲引擎由一個數(shù)據(jù)庫換為另一個數(shù)據(jù)庫。

種種需求,都需要進行數(shù)據(jù)遷移,如何平滑遷移數(shù)據(jù),遷移過程不停機,保證系統(tǒng)持續(xù)服務(wù),是文本將要討論的問題


二、停機方案

在討論平滑遷移數(shù)據(jù)方案之前,先看下不平滑的停機數(shù)據(jù)遷移方案,主要分三個步驟。

掛公告,停服務(wù)

步驟一一個類似“為了給廣大用戶提供更好的服務(wù),服務(wù)器會在凌晨0:00-0:400進行停機維護”的公告,并在對應(yīng)時段進行停機,這個時段系統(tǒng)沒有流量進入。

離線遷移數(shù)據(jù)

步驟二:停機后,研發(fā)一個離線的數(shù)據(jù)遷移工具,進行數(shù)據(jù)遷移。針對第一節(jié)的三類需求,會分別開發(fā)不同的數(shù)據(jù)遷移工具。

(1)底層表結(jié)構(gòu)變更需求:開發(fā)舊表導(dǎo)新表的工具

(2)分庫個數(shù)變換需求:開發(fā)2庫導(dǎo)3庫的工具

(3)底層存儲介質(zhì)變換需求:開發(fā)Mongo導(dǎo)Mysql工具

切到新庫

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

(1)底層表結(jié)構(gòu)變更需求:服務(wù)要升級到訪問新表

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

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


總的來說,停機方案是相對直觀和簡單的,但對服務(wù)的可用性有影響,許多游戲公司的服務(wù)器升級,游戲分區(qū)與合區(qū),可能會采用類似的方案。

除了影響服務(wù)的可用性,這個方案還有一個缺點,就是必須在指定時間完成升級,這個對研發(fā)、測試、運維同學(xué)來說,壓力會非常大,一旦出現(xiàn)問題例如數(shù)據(jù)不一致,必須在規(guī)定時間內(nèi)解決,否則只能回滾。根據(jù)經(jīng)驗,人壓力越大越容易出錯,這個缺點一定程度上是致命的。

無論如何,停機方案并不是今天要討論的重點,接下來看一下常見的平滑數(shù)據(jù)遷移方案。 

三、平滑遷移-追日志法

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

通過舊的服務(wù)訪問舊的數(shù)據(jù)

數(shù)據(jù)遷移前,上游業(yè)務(wù)應(yīng)用通過舊的服務(wù)訪問舊的數(shù)據(jù)。

平滑遷移步驟一

步驟一:服務(wù)進行升級,記錄“對舊庫上的數(shù)據(jù)修改”的日志(這里的修改,為數(shù)據(jù)的insert, delete, update),這個日志不需要記錄詳細數(shù)據(jù),主要記錄:

(1)被修改的庫

(2)被修改的表

(3)被修改的唯一主鍵

具體新增了什么行,修改后的數(shù)據(jù)格式是什么,不需要詳細記錄。這樣的好處是,不管業(yè)務(wù)細節(jié)如何變化,日志的格式是固定的,這樣能保證方案的通用性。


這個服務(wù)升級風險較?。?/p>

(1)寫接口是少數(shù)接口,改動點較少

(2)升級只是增加了一些日志,對業(yè)務(wù)功能沒有任何影響

平滑遷移步驟二

步驟二研發(fā)一個數(shù)據(jù)遷移工具,進行數(shù)據(jù)遷移。這個數(shù)據(jù)遷移工具和離線遷移工具一樣,把舊庫中的數(shù)據(jù)轉(zhuǎn)移到新庫中來。


這個小工具的風險較小:

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

(2)小工具的復(fù)雜度較低

(3)任何時間發(fā)現(xiàn)問題,都可以把新庫中的數(shù)據(jù)干掉重來

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


數(shù)據(jù)遷移完成之后,就能夠切到新庫提供服務(wù)了么?

答案是否定的,在數(shù)據(jù)遷移的過程中,舊庫依然對線上提供著服務(wù),庫中的數(shù)據(jù)隨時可能變化,這個變化并沒有反映到新庫中來,于是舊庫和新庫的數(shù)據(jù)并不一致,所以不能直接切庫,需要將數(shù)據(jù)追平。


哪些數(shù)據(jù)發(fā)生了變化呢?

步驟一中日志里記錄的不就是么?

平滑遷移步驟三

步驟三研發(fā)一個讀取日志并遷移數(shù)據(jù)的小工具,要把步驟二遷移數(shù)據(jù)過程中產(chǎn)生的差異數(shù)據(jù)追平。這個小工具需要做的是:

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

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

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

無論如何,原則是數(shù)據(jù)以舊庫為準


這個小工具的風險也很?。?/p>

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

(2)小工具的復(fù)雜度較低

(3)任何時間發(fā)現(xiàn)問題,大不了從步驟二開始重來

(4)可以限速慢慢重放日志,技術(shù)同學(xué)沒有時間壓力


日志重放之后,就能夠切到新庫提供服務(wù)了么?

答案依然是否定的,在日志重放的過程中,舊庫中又可能有數(shù)據(jù)發(fā)生了變化,導(dǎo)致數(shù)據(jù)不一致,所以還是不能切庫,需要進一步讀取日志,追平記錄??梢钥吹?,重放日志追平數(shù)據(jù)的程序是一個while(1)的程序,新庫與舊庫中的數(shù)據(jù)追平也會是一個“無限逼近”的過程


什么時候數(shù)據(jù)會完全一致呢?

平滑遷移步驟四

步驟四:在持續(xù)重放日志,追平數(shù)據(jù)的過程中,研發(fā)一個數(shù)據(jù)校驗的小工具,將舊庫和新庫中的數(shù)據(jù)進行比對,直到數(shù)據(jù)完全一致


這個小工具的風險依舊很?。?/p>

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

(2)小工具的復(fù)雜度較低

(3)任何時間發(fā)現(xiàn)問題,大不了從步驟二開始重來

(4)可以限速慢慢比對數(shù)據(jù),技術(shù)同學(xué)沒有時間壓力

平滑遷移步驟五

步驟五:在數(shù)據(jù)比對完全一致之后,將流量遷移到新庫,新庫提供服務(wù),完成遷移。


如果步驟四數(shù)據(jù)一直是99.9%的一致,不能完全一致,也是正常的,可以做一個秒級的舊庫readonly,等日志重放程序完全追上數(shù)據(jù)后,再進行切庫切流量。 

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

四、平滑遷移-雙寫法

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

通過舊的服務(wù)訪問舊的數(shù)據(jù)

數(shù)據(jù)遷移前,上游業(yè)務(wù)應(yīng)用通過舊的服務(wù)訪問舊的數(shù)據(jù)。

雙寫法步驟一

步驟一服務(wù)進行升級,對“對舊庫上的數(shù)據(jù)修改”(這里的修改,為數(shù)據(jù)的insert, delete, update),在新庫上進行相同的修改操作,這就是所謂的“雙寫”,主要修改操作包括:

(1)舊庫與新庫的同時insert

(2)舊庫與新庫的同時delete

(3)舊庫與新庫的同時update

由于新庫中此時是沒有數(shù)據(jù)的,所以雙寫舊庫與新庫中的affect rows可能不一樣,不過這完全不影響業(yè)務(wù)功能,只要不切庫,依然是舊庫提供業(yè)務(wù)服務(wù)


這個服務(wù)升級風險較?。?/p>

(1)寫接口是少數(shù)接口,改動點較少

(2)新庫的寫操作執(zhí)行成功與否,對業(yè)務(wù)功能沒有任何影響

雙寫法步驟二

步驟二:研發(fā)一個數(shù)據(jù)遷移工具,進行數(shù)據(jù)遷移。這個數(shù)據(jù)遷移工具在本文中已經(jīng)出現(xiàn)第三次了,把舊庫中的數(shù)據(jù)轉(zhuǎn)移到新庫中來。


這個小工具的風險較?。?/p>

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

(2)小工具的復(fù)雜度較低

(3)任何時間發(fā)現(xiàn)問題,都可以把新庫中的數(shù)據(jù)干掉重來

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


數(shù)據(jù)遷移完成之后,就能夠切到新庫提供服務(wù)了么?

答案是肯定的,因為前置步驟進行了雙寫,所以理論上數(shù)據(jù)遷移完之后,新庫與舊庫的數(shù)據(jù)應(yīng)該完全一致。


由于遷移數(shù)據(jù)的過程中,舊庫新庫雙寫操作在同時進行,怎么證明數(shù)據(jù)遷移完成之后數(shù)據(jù)就完全一致了呢?

分段逐步遷移圖

如上圖所示:

(1)左側(cè)是舊庫中的數(shù)據(jù),右側(cè)是新庫中的數(shù)據(jù)

(2)按照primary key從min到max的順序,分段,限速進行數(shù)據(jù)的遷移,假設(shè)已經(jīng)遷移到now這個數(shù)據(jù)段


數(shù)據(jù)遷移過程中的修改操作分別討論:

(1)假設(shè)遷移過程中進行了一個雙insert操作,舊庫新庫都插入了數(shù)據(jù),數(shù)據(jù)一致性沒有被破壞

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

         (2.1)假設(shè)這delete的數(shù)據(jù)屬于[min,now]范圍,即已經(jīng)完成遷移,則舊庫新庫都刪除了數(shù)據(jù),數(shù)據(jù)一致性沒有被破壞

         (2.2)假設(shè)這delete的數(shù)據(jù)屬于[now,max]范圍,即未完成遷移,則舊庫中刪除操作的affect rows為1,新庫中刪除操作的affect rows為0,但是數(shù)據(jù)遷移工具在后續(xù)數(shù)據(jù)遷移中,并不會將這條舊庫中被刪除的數(shù)據(jù)遷移到新庫中,所以數(shù)據(jù)一致性仍沒有被破壞

(3)假設(shè)遷移過程中進行了一個雙update操作,可以認為update操作是一個delete加一個insert操作的復(fù)合操作,所以數(shù)據(jù)仍然是一致的


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

(1)date-migrate-tool剛好從舊庫中將某一條數(shù)據(jù)X取出

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

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

這樣,會出現(xiàn)新庫比舊庫多出一條數(shù)據(jù)X。


但無論如何,為了保證數(shù)據(jù)的一致性,切庫之前,還是需要進行數(shù)據(jù)校驗的。

雙寫法步驟三

步驟三:在數(shù)據(jù)遷移完成之后,需要使用數(shù)據(jù)校驗的小工具,將舊庫和新庫中的數(shù)據(jù)進行比對,完全一致則符合預(yù)期,如果出現(xiàn)步驟二中的極限不一致情況,則以舊庫中的數(shù)據(jù)為準。


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

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

(2)小工具的復(fù)雜度較低

(3)任何時間發(fā)現(xiàn)問題,大不了從步驟二開始重來

(4)可以限速慢慢比對數(shù)據(jù),技術(shù)同學(xué)沒有時間壓力

雙寫法步驟四

步驟四:數(shù)據(jù)完全一致之后,將流量切到新庫,完成平滑數(shù)據(jù)遷移。


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

五、總結(jié)

針對互聯(lián)網(wǎng)很多“數(shù)據(jù)量較大,并發(fā)量較大,業(yè)務(wù)復(fù)雜度較高”的業(yè)務(wù)場景,在

(1)底層表結(jié)構(gòu)變更

(2)分庫個數(shù)變換

(3)底層存儲介質(zhì)變換

的眾多需求下,需要進行數(shù)據(jù)遷移,完成“平滑遷移數(shù)據(jù),遷移過程不停機,保證系統(tǒng)持續(xù)服務(wù)”有兩種常見的解決方案。


追日志法,五個步驟:

(1)服務(wù)進行升級,記錄“對舊庫上的數(shù)據(jù)修改”的日志

(2)研發(fā)一個數(shù)據(jù)遷移小工具,進行數(shù)據(jù)遷移

(3)研發(fā)一個讀取日志小工具,追平數(shù)據(jù)差異

(4)研發(fā)一個數(shù)據(jù)比對小工具校驗數(shù)據(jù)一致性

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


雙寫法,四個步驟:

(1)服務(wù)進行升級,記錄“對舊庫上的數(shù)據(jù)修改”進行新庫的雙寫

(2)研發(fā)一個數(shù)據(jù)遷移小工具,進行數(shù)據(jù)遷移

(3)研發(fā)一個數(shù)據(jù)比對小工具,校驗數(shù)據(jù)一致性

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


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


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號