互聯(lián)網(wǎng)業(yè)務(wù)變更非常快,隨著業(yè)務(wù)規(guī)模擴(kuò)大,線上的業(yè)務(wù)也會涉及重構(gòu)和遷移。比較難的就是存儲遷移,可能從前的存儲不適合新的業(yè)務(wù)模型了,例如從關(guān)系型數(shù)據(jù)庫遷移到nosql,或者數(shù)據(jù)的存儲格式發(fā)生了巨大的變化。

為什么說涉及數(shù)據(jù)遷移的業(yè)務(wù)最難呢?因為數(shù)據(jù)是有狀態(tài)的,不像邏輯和接入層,方便灰度,即使出問題馬上回滾就能恢復(fù)(如果涉及寫數(shù)據(jù)也也有問題)。然而數(shù)據(jù)是有狀態(tài)的,如果切換后發(fā)現(xiàn)新的寫存儲數(shù)據(jù)有問題,是很難修復(fù)的,也很難發(fā)現(xiàn)的。

任何遷移或更新,涉及到數(shù)據(jù)的,都有一個原則:要有驗證比對和回滾能力。

驗證比對

數(shù)據(jù)遷移后,要有辦法驗證這次遷移是成功的,沒問題的。只是從代碼上說,看,前后邏輯都一樣,肯定沒問題是靠不住的。我們要從結(jié)果,從用戶的角度來驗證,查看新老數(shù)據(jù)是否一致,是否有問題。

一般的方法是雙寫。老的數(shù)據(jù)庫還對外服務(wù),把寫操作同步一份給新數(shù)據(jù)庫,兩個庫一起寫。把有改動的用戶數(shù)據(jù)同步過來,然后再寫一個同步程序,把所有用戶的全量數(shù)據(jù)導(dǎo)過來。檢測程序,能夠根據(jù)每個key進(jìn)行比對,定期把庫里所有的數(shù)據(jù)進(jìn)行新老比對,當(dāng)比對率達(dá)到閾值以后。還要做一個數(shù)據(jù)比對層,用戶讀寫的時候先走比對層,同時給新老兩個邏輯層同步包,也接收回包。然后把回包進(jìn)行二進(jìn)制比對,保證返回給用戶的數(shù)據(jù)也是一致的。

當(dāng)都達(dá)到一致之后,就可以切換了,切換后以新層為主,老層為輔,也接收同步數(shù)據(jù)。

回滾數(shù)據(jù)能力

為什么驗證比對里最后老層還要接收新層的同步呢,直接切換不好嗎?是因為萬一切換后出現(xiàn)bug,發(fā)現(xiàn)其他地方有問題,可以馬上回滾回老數(shù)據(jù)。保證線上服務(wù)正常,給開發(fā)修復(fù)bug留下充足的時間,不會有很大的時間壓力。如果不能馬上回滾,只能在線修bug。后續(xù)的每次發(fā)布修改,對開發(fā)的個人能力和狀態(tài)依賴大,不可控因素太多。很難保證服務(wù)質(zhì)量。

再多說一下,由于是重構(gòu),有時會發(fā)現(xiàn)從前數(shù)據(jù)里的錯數(shù)據(jù),或邏輯bug。不建議馬上修復(fù),新的要先和老的邏輯數(shù)據(jù)對齊,穩(wěn)定后再修復(fù)老bug。否則bug改完后就沒有一個標(biāo)桿來驗證數(shù)據(jù)是否一致了。

有人會說,弄這么多,得多久能完成遷移啊,效率太低。考試題目做的再快,不對也是白搭,之所以做這么多,就是保證萬無一失。欲速則不達(dá),如果數(shù)據(jù)錯了再去修補(bǔ),時間花費(fèi)的更多,而且有時是補(bǔ)不回來的,只能回檔,那時給用戶造成的損失就大了。在QQ后臺,每次數(shù)據(jù)遷移都要經(jīng)過幾周的發(fā)布比對才能切換,重大的數(shù)據(jù)層重構(gòu),沒個一年半載達(dá)到六個9的一致性,根本不會切換的。這也是為什么一次次在行動的火車上換發(fā)動機(jī)能夠成功的原因!

總結(jié)

涉及到數(shù)據(jù)的變更發(fā)布,要有比對能力,有從結(jié)果出發(fā)的方法,能夠驗證數(shù)據(jù)遷移后是正常的才可以。只從代碼邏輯層面分析是不靠譜的。

要有plan B,如果真的有問題,要能夠回滾,有回旋的余地。

做到以上所說,才能立于平滑遷移數(shù)據(jù)服務(wù)的不敗之地!

分類: 心得體會