一、NameNode高可用整體架構(gòu)
架構(gòu):
NameNode組建包括:
(1)Active NameNode——主NameNode掖看,可以對(duì)外提供讀寫(xiě)服務(wù)
(2)standby NameNode——備NameNode
(3)ZKFailoverController——主備切換控制器丈氓,獨(dú)立進(jìn)程運(yùn)行,可及時(shí)檢測(cè)到NameNode的健康狀況熊尉,不依賴與手動(dòng)切換
(4)Zookeeper集群——為主備切換控制器提供主備選舉支持
(5)共享存儲(chǔ)系統(tǒng)——是實(shí)現(xiàn)NameNode高可用性的關(guān)鍵裸弦,對(duì)元數(shù)據(jù)(并不是所有)進(jìn)行共享和存儲(chǔ),而主NameNode和備NameNode通過(guò)其實(shí)現(xiàn)數(shù)據(jù)的同步楷掉。
(6)DataNode——同時(shí)向主NameNode和備NameNode 上報(bào)數(shù)據(jù)塊的位置信息
二厢蒜、NameNode的主備切換
流程圖:
NameNode主備切換主要是由zkfc完成,主要由HealthMonitor烹植、ZKFailoverController和ActiveStandbyElector三個(gè)組件協(xié)同完成斑鸦。
zkfc作為獨(dú)立進(jìn)程啟動(dòng),啟動(dòng)時(shí)創(chuàng)建HealthMonitor和ActiveStandbyElector兩個(gè)主要內(nèi)部組件刊橘。
HealthMonitor主要負(fù)責(zé)檢測(cè)NameNode 的健康狀態(tài)鄙才,如果檢查到NameNode的健康狀態(tài)發(fā)生改變,它會(huì)回調(diào)ZKFailoverController的相應(yīng)方法進(jìn)行自動(dòng)的主備選舉促绵。
ActiveStandbyElector主要負(fù)責(zé)完成自動(dòng)的主備選舉攒庵,它內(nèi)部封裝了Zookeeper的處理邏輯,一旦主備選舉完成败晴,就會(huì)回調(diào)ZKFailoverController的相應(yīng)方法進(jìn)行主備切換浓冒。
ZKFC監(jiān)控Active NameNode健康狀況,一旦發(fā)生問(wèn)題尖坤,利用Zookeeper 集群進(jìn)行選舉稳懒。再?zèng)Q定NameNode到底是Active NameNode還是standby NameNode。
三慢味、NameNode的共享存儲(chǔ)
NameNode 在執(zhí)行 HDFS 客戶端提交的創(chuàng)建文件或者移動(dòng)文件這樣的寫(xiě)操作的時(shí)候场梆,會(huì)首先把這些操作記錄在 EditLog 文件之中墅冷,然后再更新內(nèi)存中的文件系統(tǒng)鏡像。內(nèi)存中的文件系統(tǒng)鏡像用于 NameNode 向客戶端提供讀服務(wù)或油,而 EditLog 僅僅只是在數(shù)據(jù)恢復(fù)的時(shí)候起作用寞忿。
NameNode 會(huì)定期對(duì)內(nèi)存中的文件系統(tǒng)鏡像進(jìn)行 checkpoint 操作,在磁盤上生成 FSImage 文件顶岸。在 NameNode 啟動(dòng)的時(shí)候會(huì)進(jìn)行數(shù)據(jù)恢復(fù)腔彰,首先把 FSImage 文件加載到內(nèi)存中形成文件系統(tǒng)鏡像,然后再把 EditLog 之中 FsImage 的結(jié)束事務(wù) id 之后的 EditLog 回放到這個(gè)文件系統(tǒng)鏡像上辖佣。
基于 QJM 的共享存儲(chǔ)系統(tǒng)主要用于保存 EditLog霹抛,并不保存 FSImage 文件。FSImage 文件還是在 NameNode 的本地磁盤上卷谈。每次 NameNode 寫(xiě) EditLog 的時(shí)候杯拐,除了向本地磁盤寫(xiě)入 EditLog 之外,也會(huì)并行地向 JournalNode 集群之中的每一個(gè) JournalNode 發(fā)送寫(xiě)請(qǐng)求世蔗,只要大多數(shù) (majority) 的 JournalNode 節(jié)點(diǎn)返回成功就認(rèn)為向 JournalNode 集群寫(xiě)入 EditLog 成功藕施。如果有 2N+1 臺(tái) JournalNode,那么根據(jù)大多數(shù)的原則凸郑,最多可以容忍有 N 臺(tái) JournalNode 節(jié)點(diǎn)掛掉。
當(dāng)處于 Active 狀態(tài)的 NameNode 調(diào)用 FSEditLog 類的 logSync 方法來(lái)提交 EditLog 的時(shí)候矛市,會(huì)通過(guò) JouranlSet 同時(shí)向本地磁盤目錄和 JournalNode 集群上的共享存儲(chǔ)目錄寫(xiě)入 EditLog芙沥。寫(xiě)入 JournalNode 集群是通過(guò)并行調(diào)用每一個(gè) JournalNode 的 QJournalProtocol RPC 接口的 journal 方法實(shí)現(xiàn)的,如果對(duì)大多數(shù) JournalNode 的 journal 方法調(diào)用成功浊吏,那么就認(rèn)為提交 EditLog 成功而昨,否則 NameNode 就會(huì)認(rèn)為這次提交 EditLog 失敗。
當(dāng) NameNode 進(jìn)入 Standby 狀態(tài)之后找田,會(huì)啟動(dòng)一個(gè) EditLogTailer 線程歌憨。這個(gè)線程會(huì)定期調(diào)用 EditLogTailer 類的 doTailEdits 方法從 JournalNode 集群上同步 EditLog,然后把同步的 EditLog 回放到內(nèi)存之中的文件系雖然 Active NameNode 向 JournalNode 集群提交 EditLog 是同步的墩衙,但 Standby NameNode 采用的是定時(shí)從 JournalNode 集群上同步 EditLog 的方式务嫡,那么 Standby NameNode 內(nèi)存中文件系統(tǒng)鏡像有很大的可能是落后于 Active NameNode 的,所以 Standby NameNode 在轉(zhuǎn)換為 Active NameNode 的時(shí)候需要把落后的 EditLog 補(bǔ)上來(lái)漆改。
處于 Standby 狀態(tài)的 NameNode 轉(zhuǎn)換為 Active 狀態(tài)的時(shí)候心铃,有可能上一個(gè) Active NameNode 發(fā)生了異常退出,那么 JournalNode 集群中各個(gè) JournalNode 上的 EditLog 就可能會(huì)處于不一致的狀態(tài)挫剑,所以首先要做的事情就是讓 JournalNode 集群中各個(gè)節(jié)點(diǎn)上的 EditLog 恢復(fù)為一致去扣。另外,當(dāng)前處于 Standby 狀態(tài)的 NameNode 的內(nèi)存中的文件系統(tǒng)鏡像有很大的可能是落后于舊的 Active NameNode 的樊破,所以在 JournalNode 集群中各個(gè)節(jié)點(diǎn)上的 EditLog 達(dá)成一致之后愉棱,接下來(lái)要做的事情就是從 JournalNode 集群上補(bǔ)齊落后的 EditLog唆铐。只有在這兩步完成之后,當(dāng)前新的 Active NameNode 才能安全地對(duì)外提供服務(wù)奔滑。