記一次分佈式數據庫啓動異常分析

今天在測試環境遇到一個很有意思的問題,我們在測試一款分佈式數據庫,這款分佈式數據庫底層是基於postgresql做的,現象大致是這樣的,我們在重啓數據庫集羣后發現某臺機器的數據節點啓動失敗,然後去那臺機器上發現進程確實沒有啓動。然後看了下運行日誌,定位到了啓動失敗的原因,是內存不夠用了,查了下該節點上還運行着其他數據庫,由於其他數據庫也佔了一部分內存,造成該節點數據庫由於內存不足啓動失敗。

 

上面說的啓動失敗只是一下一個導火索,真正的異常發生在後面,啓動失敗後查詢了一下集羣狀態,發現該數據節點的主節點狀態爲down,數據節點目前是一主兩備的架構,使用quroum作爲一致性協議,那麼三節點的狀態下只要有一個備返回就可以提交。

 

集羣管理軟件檢測到數據節點A主節點down後會自動觸發切換,選舉出一個備節點B接替主節點,切換完成後有意思的事情出現了,查看集羣狀態發現原來的A主節點和C備節點處於standby rebuilding狀態,因爲看到rebuilding,第一感覺是數據節點重建了,這時腦子裏第一反應是去A機上去看看數據目錄大小,看是否真的重建了,果然,數據目錄一直在增長,最終兩個節點重建成功,主備關係恢復,整個過程都是集羣管理自動完成,沒有人工參與,而且在備節點重建過程中業務可以正常進行。

 

這裏有個值得思考的問題,重啓後主節點無法啓動備節點升主是意料之內,但是切換後爲什麼會做rebuilding?後來思考了下,終於想通了。

 

我們先來看看postgresql的三種停止模式:smart/fast/immediate

 

Smart:等待所有活躍的會話及備份關閉,類似於oracle的shutdown normal

Fast:服務器不會等待客戶端連接關閉而是直接終止,所有未提交的事務會被回滾,這也是默認的停止模式,類似於oracle的shutdown immediate

Immediate:強制關閉,類似於斷電,在實例重新啓動時會做實例恢復,類似於oracle的shutdown abort

 

再回到我們的案例,我們可以先想象一下異常停止集羣。如果異常停止,那麼就可能出現殘留信息,master重新啓動時需要利用之前的wal日誌進行實例恢復,這部分wal是沒有傳遞到備機的,也就是說主機多一部分殘留的日誌,這時啓動集羣如果正好A及master由於某種原因(這次是內存原因)無法啓動,那麼觸發切換後新的master B機就比原master A機多一些日誌,這樣的話b機產生的wal如果傳給a機可能造成不一致。這時集羣管理爲了保證一致性將原master A機進行rebuild也是合情合理,rebuild過程中B和A的主備關係失效,所以B機升主後其實是在裸跑,不會影響業務,待原A機rebuild完成後和B機的同步關係恢復。

 

上面我們大致分析了一下原因,但其實我停止集羣的時候並沒有使用immediate方式異常停止,而是正常停止的。按說正常使用fast模式停止集羣,會進行checkpoint,同時wal會傳到備機,應該不會產生主機多日誌的情況,這又是什麼原因呢?

 

後來細想一下發現,因爲是分佈式的,集羣停止時是按照stop node1.2.3.4.5.6來下發停止命令的,而我的A機是最後一臺機器node6,B機和C機是前面的兩臺,所以說B機和C機可能會先停止,而集羣的機制是爲了保證高可用,在備數據節點宕機主數據節點存活時,依然不影響業務,主節點依然可以寫入,所以當BC機停止後這時A機其實還在寫入併產生wal日誌,但是已經無法同步給BC的slave節點了。這樣就造成master比slave的數據多,這時進行切換就需要將原master重建。

 

技術人要有精益求精的精神,探究技術細節並且記錄它也是一件很有意思的事情,加油吧。

 

更多精彩文章請關注我的公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章