水平分庫如何做到平滑擴展

這個對於我們常用的分庫分表方案來說,有很大的優勢,分庫分表的擴容是一件頭疼的問題,如果採用對db層做一致性hash,或是中間價的支持,它的成本過於高昂了,如果不如此,只能停機維護來處理,對高可用性會產生影響。

那是否有方案,既可以快速擴展,又不降低可用性?這一篇,我們聊聊分庫分表的擴展方案,供大家一起探討。

一、水平分庫擴展問題


爲了增加db的併發能力,常見的方案就是對數據進行sharding,也就是常說的分庫分表,這個需要在初期對數據規劃有一個預期,從而預先分配出足夠的庫來處理。

比如目前規劃了3個數據庫,基於uid進行取餘分片,那麼每個庫上的劃分規則如下:

images/wHMizQtWADJhcHtsC2CsBSSd3EpwyT3C.png


如上我們可以看到,數據可以均衡的分配到3個數據庫裏面。


但是,如果後續業務發展的速度很快,用戶量數據大量上升,當前容量不足以支撐,應該怎麼辦?


需要對數據庫進行水平擴容,再增加新庫來分解。新庫加入之後,原先sharding到3個庫的數據,就可以sharding到四個庫裏面了

images/c7HNwBfyrdHEcwcrFNeZadescxKSTRTJ.png


不過此時由於分片規則進行了變化(uid%3 變爲uid%4),大部分的數據,無法命中在原有的數據庫上了,需要重新分配,大量數據需要遷移。


比如之前uid1通過uid1%3 分配在A庫上,新加入庫D之後,算法改爲uid1%4 了,此時有可能就分配在B庫上面了。如果你有看到之前《一致性哈希的原理與實踐》,就會發現新增一個節點,大概會有90%的數據需要遷移,這個對DB同學的壓力還是蠻大的,那麼如何應對?


一般有以下幾種方式。

 

二、停服遷移


停服遷移是最常見的一種方案了,一般如下流程:

1.預估停服時間,發佈停服公告


2.停服,通過事先做好的數據遷移工具,按照新的分片規則,進行遷移


3.修改分片規則


4.啓動服務


我們看到這種方式比較安全,停服之後沒有數據寫入,能夠保證遷移工作的正常進行,沒有一致性的問題。唯一的問題,就是停服了和時間壓力了。


1.停服,傷害用戶體驗,同時也降低了服務器的可用性


2.必須在制定時間內完成遷移,如果失敗,需要擇日再次進行。同時增加了開發人員的壓力,容易發生大的事故


3.數據量的巨大的時候,遷移需要大量時間


那有沒有其他方式來改進一下,我們看下以下兩種方案。

 

三、升級從庫


線上數據庫,我們爲了保持其高可用,一般都會每臺主庫配一臺從庫,讀寫在主庫,然後主從同步到從庫。如下,A,B是主庫,A0和B0是從庫。

images/8rEfR77YcB33b43XteBhHQ35DK6MSYNz.png


此時,當需要擴容的時候,我們把A0和B0升級爲新的主庫節點,如此由2個分庫變爲4個分庫。同時在上層的分片配置,做好映射,規則如下:


uid%4=0和uid%4=2的分別指向A和A0,也就是之前指向uid%2=0的數據,分裂爲uid%4=0和uid%4=2


uid%4=1和uid%4=3的指向B和B0,也就是之前指向uid%2=1的數據,分裂爲uid%4=1和uid%4=3


因爲A和A0庫的數據相同,B和B0數據相同,所以此時無需做數據遷移即可。只需要變更一下分片配置即可,通過配置中心更新,無需重啓。

images/Tkp7EbsE7nFDs6hmZAiKkY8fTJaWEr6H.png


由於之前uid%2的數據分配在2個庫裏面,此時分散到4個庫中,由於老數據還存在(uid%4=0,還有一半uid%4=2的數據),所以需要對冗餘數據做一次清理。


而這個清理,不會影響線上數據的一致性,可是隨時隨地進行。


處理完成以後,爲保證高可用,以及下一步擴容需求。可以爲現有的主庫再次分配一個從庫。

images/nNGSc2YkRE84wRWaQ34ZYTs722szGAnz.png


總結一下此方案步驟如下:


1.修改分片配置,做好新庫和老庫的映射。


2.同步配置,從庫升級爲主庫


3.解除主從關係


4.冗餘數據清理


5.爲新的數據節點搭建新的從庫


四、雙寫遷移


雙寫的方案,更多的是針對線上數據庫遷移來用的,當然了,對於分庫的擴展來說也是要遷移數據的,因此,也可以來協助分庫擴容的問題。


原理和上述相同,做分裂擴容,只是數據的同步方式不同了。


1.增加新庫寫鏈接


雙寫的核心原理,就是對需要擴容的數據庫上,增加新庫,並對現有的分片上增加寫鏈接,同時寫兩份數據。


因爲新庫的數據爲空,所以數據的CRUD對其沒有影響,在上層的邏輯層,還是以老庫的數據爲主。

images/BxbktjnewEeDZtnsp5HybpyMck7mEhGn.png


2.新老庫數據遷移


通過工具,把老庫的數據遷移到新庫裏面,此時可以選擇同步分裂後的數據(1/2)來同步,也可以全同步,一般建議全同步,最終做數據校檢的時候好處理。

images/iANnkxfQPXxH8cfWNSKYdRSdFZyHXZFd.png


3.數據校檢


按照理想環境情況下,數據遷移之後,因爲是雙寫操作,所以兩邊的數據是一致的,特別是insert和update,一致性情況很高。但真實環境中會有網絡延遲等情況,對於delete情況並不是很理想,比如:


A庫刪除數據a的時候,數據a正在遷移,還沒有寫入到C庫中,此時C庫的刪除操作已經執行了,C庫會多出一條數據。


此時就需要做好數據校檢了,數據校檢可以多做幾遍,直到數據幾乎一致,儘量以舊庫的數據爲準。


 


4.分片配置修改


數據同步完畢,就可以把新庫的分片映射重新處理了,還是按照老庫分裂的方式來進行,


u之前uid%2=0,變爲uid%4=0和uid%4=2的


uid%2=1,變爲uid%4=1和uid%4=3的。

images/5Bck6ZNhDeC2Y6CaNinFPrRb3eEccEPE.png


引用:


https://mp.weixin.qq.com/s/BLOneOs-cPxP_9b5eH8oQA


來源:https://my.oschina.net/u/1859679/blog/1577049

發佈了63 篇原創文章 · 獲贊 43 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章