大型互聯(lián)網(wǎng)系統(tǒng)數(shù)據(jù)庫切換方案
前言
互聯(lián)網(wǎng)公司中,有不少大型系統(tǒng),如商城的價(jià)格系統(tǒng),優(yōu)惠券系統(tǒng),等等。這些系統(tǒng)在一年又一年的運(yùn)營(yíng)之后,數(shù)據(jù)存儲(chǔ)量將相當(dāng)龐大,我們最終會(huì)做一些數(shù)據(jù)庫方面的升級(jí),簡(jiǎn)單粗暴的方法就是切庫,以滿足更多的數(shù)據(jù)庫存儲(chǔ)空間、更好的數(shù)據(jù)讀取性能。
然而切庫的操作,對(duì)于系統(tǒng)而言,無異于換血操作,是一件相當(dāng)危險(xiǎn)的操作,那么如何平穩(wěn),或者說損失最小的情況下,將系統(tǒng)的數(shù)據(jù)庫進(jìn)行切換呢?這就是本文要分享的內(nèi)容了。
需求
很多情況下,我們可以通過對(duì)系統(tǒng)進(jìn)行優(yōu)化就能滿足系統(tǒng)的性能要求的情況下,我們是不會(huì)選擇切庫這個(gè)方案的。筆者經(jīng)歷的切庫情況,有以下兩種:

數(shù)據(jù)庫中間件
- 原先的數(shù)據(jù)庫使用的是通過Docker安裝的MySQL,切換為公司內(nèi)部的數(shù)據(jù)庫中間件(也稱分布式數(shù)據(jù)庫,類似阿里云的RDS),項(xiàng)目中的代碼程序不用做過多的分庫分表改造,由數(shù)據(jù)庫中間件幫我們做了這個(gè)事情,我們的數(shù)據(jù)存儲(chǔ)很自然地變?yōu)?strong>多分片存儲(chǔ)了;
- 原先的數(shù)據(jù)庫為公司內(nèi)部的數(shù)據(jù)庫中間件,由于分片過少,需要擴(kuò)容分片。而數(shù)據(jù)庫中間件不能很好地擴(kuò)縮容分片,進(jìn)行少分片數(shù)據(jù)庫中間件切多分片數(shù)據(jù)庫中間件切換;
方案
有了以上的共識(shí),最后還是選擇切庫方案的話,通常我們會(huì)選擇在夜深人靜時(shí)分,即系統(tǒng)訪問量最少的情況下,像電商一般是半夜3點(diǎn)半左右,進(jìn)行切庫操作,避免切庫過程造成過多的臟數(shù)據(jù)。
當(dāng)然,我們的系統(tǒng),需要提前開發(fā)好切庫相關(guān)的代碼,如新庫SQL適配、切庫過程的開關(guān)引入,等等。
至于具體的將數(shù)據(jù)庫從A切換到B的步驟,有以下幾點(diǎn):

切庫流程
1.將A庫中的數(shù)據(jù),全量同步到B庫中,同時(shí)保持增量同步。
這樣我們?nèi)绻麑?shù)據(jù)庫連接從A改為B時(shí),讀取的數(shù)據(jù),是一樣的,當(dāng)然期間的數(shù)據(jù)庫同步延遲是不可避免的。而數(shù)據(jù)的同步,可以使用阿里巴巴開源的中間件canal。
2.將A庫進(jìn)行停寫。
一旦A庫進(jìn)行停寫了,那么B庫在很短的時(shí)間延遲之后,將獲得同A一樣的全量數(shù)據(jù)了,然后我們就可以把數(shù)據(jù)庫同步斷開。
3.將系統(tǒng)的數(shù)據(jù)庫鏈接切換到B庫。
我們的系統(tǒng)需要事先鏈接兩套數(shù)據(jù)庫,通過開關(guān)控制數(shù)據(jù)庫鏈接,如此我們就可以通過極短的時(shí)間內(nèi),將系統(tǒng)的數(shù)據(jù)庫鏈接進(jìn)行切換。























