如今不少高可用系統爲了應對極端狀況,好比主機宕機、網絡故障以及機房宕機等災難的發生,一般會部署主備架構(雙機房),或者雙活架構(雙機房),甚至多活架構(三個機房或者以上),mongodb自然就適合部署雙機房或者多機房,可是在發生機房宕機災難時,也會遇到沒法選舉主節點的問題,本文重點討論在主備或者雙活架構下的mongodb的部署方案和切換方案,下文中的討論以主備架構爲例(雙活同理)。mongodb
在主備架構部署方案中,用戶請求都是路由到主機房,備用機房無用戶請求,爲了簡化示意,這裏先把cdn、dns、waf等部分略去,重點突出應用和mongo集羣內部節點的部署結構,以下圖:服務器
從上圖能夠看到,負載均衡和應用服務部分都是主備架構,mongodb集羣是一體的(兩邊都會處理請求),沒有主備之分,只是部署在兩個機房而已。網絡
固然,這種方式下,mongodb集羣的資源利用率會高一些,不存在上層備用機房的應用服務的資源閒置浪費的問題。架構
在主備架構環境中,mongodb的高可用部署方案,推薦複製組內的節點數是奇數(好比3個節點,1主2從),此時存在一個機房部署2個節點,一個機房部署1個節點,當部署2個節點的機房宕機時,因爲另一個機房只有1個節點,而mongodb的選舉協議是raft一致性協議,此時是沒法選舉出主節點的(要求存活節點數大於原節點數的1/2),致使mongodb服務的不可用,示意圖以下:負載均衡
針對章節3中遇到的問題,咱們調整了部署方案,即在備用機房準備一個備用節點,平時是不啓動的,僅在主機房災難發生時,才啓動該備用節點,示意圖以下:運維
部署方案已經有了,下面談一下主備切換方案,當主機房發生災難時,咱們要解決兩個問題:分佈式
1. 怎麼啓動先前的備用節點。.net
2. 怎麼讓剛剛啓動的備用節點加入到複製組中,不然是沒法參與主節點選舉的。cdn
在備用節點上準備好啓動腳本,而後使用運維軟件(例如saltstack)發送啓動命令,便可啓動備用節點。blog
咱們知道若是要把一個新的節點加入複製組,是須要在主節點執行rs.add命令的,可是在災難發生時,因爲尚未主節點,是沒法使用這個辦法的,所以須要換一個思路,即讓備用節點「替換」原主機房的從節點,這裏的「替換」是指讓複製組的其餘成員認爲該備用節點,就是原來的從節點,技術方案以下:
1. 首先複製組內的成員,在加入複製組時,使用域名替換ip的方式,例如:rs.add("shardA1.mongodb.net:27017"),同時修改mongodb集羣全部服務器的/etc/hosts文件,配置shardA1.mongodb.net和IP的映射關係。
2. 在災難發生時,先把mongodb集羣內全部服務器的/etc/hosts中shardA1.mongodb.net對應的IP修改成備用節點的IP,再啓動備用節點,此時複製組內的其餘節點能快速連上新的節點。
解釋一下,爲何把域名和IP的映射關係配置到hosts文件而不是配置到dns服務器,主要是考慮到修改hosts文件生效更快,從而快速選舉出主節點。
1. 該方案比較大的亮點是經過修改/etc/hosts文件的方式,讓新的節點能夠加入集羣,從而快速完成主節點選舉。
2. 該方案是一個比較通用的方案,適合不少分佈式的系統使用,好比zookeeper等。
固然,在實施時,須要考慮主備雙向切換,主備切換後監控原主機房的原從節點是否被啓動等異常情景。
以上方案有任何不妥之處,歡迎斧正。