線上進行分庫分表中介軟體的平滑升級,正所謂藝高人膽大

架構擺渡人發表於2022-01-27

大家好,我是架構擺渡人。這是實踐經驗系列的第十篇文章,這個系列會給大家分享很多在實際工作中有用的經驗,如果有收穫,還請分享給更多的朋友。

故事還要從N年前說起,那時業務發展的比較快,資料每天增長比較多。很快就經常出現慢SQL各種問題,拆庫迫在眉睫。為了快速上線,直接在應用中進行拆分規則的處理,也就是將分庫分表的邏輯在客戶端進行處理,這樣的方式簡單,效能也不錯。

過了一年多,技術部加了好多人,細分的團隊也更多了。老專案用的自研的客戶端分庫分表方式,有一些新團隊內部用的開源的框架。隨著技術部規模越來越大,我們也有了自己的中介軟體團隊。CTO想統一技術棧,分庫分表中介軟體是排在第一位要進行統一的,方便統一維護和升級。

於是,中介軟體團隊研發了一款分庫分表中介軟體,類似於開源的Mycat之類的,是一個代理服務,這個服務就是MySQL的協議,我們的應用程式可以直接把它當做一個資料庫進行連線即可。

對於這種中介軟體的替換,最簡單的方式當然就是直接替換,然後釋出即可。但是如果這個中介軟體沒有經過長時間業務的考驗,你會覺得它很穩定嗎?如果不穩定,後面出問題了怎麼辦? 所以,在上線這個中介軟體切換的時候,大家討論了很久,最終定了兩種方案來實施。

方案一:獨立分支,獨立節點灰度

方案一比較簡單,實現成本較低。也就是單獨切一個分支進行改造,改造完成後,不立馬合入master分支,而是直接用這個功能分支進行釋出,但是隻釋出一個節點。

這樣即使有問題,影響面也比較小。停止服務即可立馬回滾,驗證一段時間沒有問題,就可以將程式碼合入master進行全量釋出。

如果,用了一段時間後,新的代理中介軟體不穩定,那麼此時是沒辦法立馬回滾的,變成了強依賴。此方案雖然成本低,但是穩定性考慮的一般。

方案二:多資料來源並存,線上灰度

方案二,實現過程較為複雜,工作量也比較大,但是穩定可靠。下面來介紹下多資料來源並存,線上灰度的方式。

首先,目前我們的專案中用的還是之前自己寫的一套方案,本地分庫分表的。如果想要保證在出問題的時候能夠及時切回來,所以就不能採取直接替換的方式,也就是之前的所有資料來源都要保留。

至於新的中介軟體,我們會配置一個新的資料來源,所以專案中就有兩套資料來源。那麼只需要在我們對資料庫進行增刪改查操作的時候,動態進行資料來源切換,就可以實現線上灰度邏輯。

灰度可以直接在介面級別進行,這樣即使出問題,也隻影響某個介面。而且你可以從不重要的介面開始灰度。灰度的核心邏輯無非就是控制AbstractRoutingDataSource的返回值,返回哪個資料來源,那麼這次SQL的執行將由哪個資料來源負責。

我們是Spring Cloud架構,所有介面都是Http協議,所以寫了一個Http Filter進行處理。通過配置灰度的規則,然後給要灰度的介面設定一個值,這個值儲存到ThreadLocal中,在AbstractRoutingDataSource中使用,這樣就完成了整個灰度的控制。

另外,這裡還需要注意的是,有一些非同步的處理要關注,比如MQ的消費是不經過Http Filter,所以對於MQ的消費你需要單獨進行灰度的控制。

同時需要注意的是你的DB的連線數是否夠用,因為採用本方案,連線數會翻倍,需要確認。

通過這個方案,我們將灰度做到了最小粒度,介面級別。同時程式碼也可以合入master分支一起釋出。釋出的時候預設還是老的資料來源,對現有業務不影響。

釋出完成後,通過配置開啟灰度邏輯,慢慢灰度,灰度完成後所有SQL都會通過新的資料來源,也就是代理的方式進行資料庫的訪問。

假設跑了三個月,代理中介軟體出問題,我們還是可以秒級別將SQL的執行切到老的資料來源上面來保證業務的穩定性。當然不是永遠都要保留兩套資料來源,一般用個半年如果沒問題,就可以把老資料來源下掉了。

同時要注意的是在這半年期間,如果加了新的分表規則,也需要在老程式碼中維護,因為要具備隨時切回來的能力,所以必須同步,否則切回來沒有對應的分表規則,還是會報錯。

相關文章