HDFS HA 原理

HDFS HA 原理

標(biāo)簽:HDFS HA


概述

在 Hadoop 2.x 版本中,Hadoop 實(shí)現(xiàn)了 HDFS 的 HA 功能,從而解決了 HDFS 中 NameNode 單點(diǎn)問(wèn)題。

在 HDFS NameNode 的高可用架構(gòu)中涉及到了多個(gè)部分,主要包括:Active NameNode、Standby NameNode、ZKFailoverController、ZooKeeper集群和共享存儲(chǔ)系統(tǒng)。其中,Active NameNode 和 Standby NameNode 互為主備,通過(guò)共享存儲(chǔ)系統(tǒng)共享同一份元數(shù)據(jù),由 ZooKeeper 集群負(fù)責(zé)選取主 NameNode。ZKFailoverController 負(fù)責(zé)監(jiān)控 NameNode 的狀態(tài),當(dāng)主 NameNode 出現(xiàn)故障后,進(jìn)行主備切換。

下面就對(duì) HDFS 的 HA 做進(jìn)一步的介紹。

共享存儲(chǔ)系統(tǒng)

共享存儲(chǔ)系統(tǒng)可以說(shuō)是 HDFS HA 中最重要的一個(gè)部分,因?yàn)橹鱾?NameNode 需要通過(guò)共享存儲(chǔ)系統(tǒng)進(jìn)行元數(shù)據(jù)的實(shí)時(shí)同步,這樣才能保證在進(jìn)行主備切換的時(shí)候,備 NameNode 上的元數(shù)據(jù)和主 NameNode 上的是一致的,確保切換之后不會(huì)丟失數(shù)據(jù)。

在 Hadoop 社區(qū)中曾經(jīng)出現(xiàn)過(guò)多種 NameNode 共享存儲(chǔ)解決方案,但現(xiàn)在 Hadoop 中默認(rèn)的實(shí)現(xiàn)是基于 QJM(Quorum Journal Manager),因此我們這里只對(duì) QJM 的實(shí)現(xiàn)方式進(jìn)行介紹。

NameNode 元數(shù)據(jù)

在介紹具體的 QJM 實(shí)現(xiàn)之前,先對(duì) NameNode 的元數(shù)據(jù)文件做一個(gè)簡(jiǎn)單的介紹。

NameNode 的元數(shù)據(jù)文件中最主要的是兩類文件:Fsimage 和 EditLog,這兩種文件一起構(gòu)成了 NameNode 內(nèi)存中的文件系統(tǒng)鏡像。

FSImage

FSImage 是 NameNode 內(nèi)存中文件系統(tǒng)鏡像的一個(gè)快照,在 NameNode 啟動(dòng)的時(shí)候,會(huì)先把 FSImage 加載到內(nèi)存中形成文件系統(tǒng)鏡像。FSImage 是由 NameNode 生成,保存在本地磁盤(pán)上,文件名形如 fsimage_${end_txid},其中 ${end_txid} 表示這個(gè) fsimage 文件的結(jié)束事務(wù) id。

EditLog

EditLog 中保存了客戶端對(duì) HDFS 系統(tǒng)的所有更新操作,記錄在 EditLog 中的每個(gè)操作稱為一個(gè)事務(wù),每個(gè)事務(wù)都有一個(gè)整數(shù)形式的事務(wù) id 作為編號(hào)。

EditLog 文件會(huì)被分割為很多段,每一段稱為一個(gè) Segment,而 Segment 可以分為兩種:一種是處于正在寫(xiě)入狀態(tài)的,文件名形如 edits_inprogress_${start_txid},其中 ${start_txid} 表示這個(gè) Segment 的起始事務(wù) id;另一種是處于寫(xiě)入完成狀態(tài)的,文件名形如 edits_${start_txid}-${end_txid},其中 ${start_txid} 表示起始事務(wù) id,${end_txid} 表示結(jié)束事務(wù) id。

在介紹完了 NameNode 的元數(shù)據(jù)文件之后,現(xiàn)在來(lái)介紹 NameNode 是如何通過(guò) QJM 實(shí)現(xiàn)元數(shù)據(jù)共享的。

元數(shù)據(jù)共享

HDFS 是通過(guò) QJM 來(lái)實(shí)現(xiàn)的 NameNode 元數(shù)據(jù)的共享,但需要注意的是,QJM 上只保存了 EditLog 文件,F(xiàn)SImage 文件還是保存在 NameNode 的本地磁盤(pán)上。

QJM 系統(tǒng)的基本思想是來(lái)源于 Paxos 算法,由多個(gè)被稱為 Journal Node 的節(jié)點(diǎn)組成,每個(gè) Journal Node 上都保存了相同的數(shù)據(jù)。當(dāng)向 QJM 中寫(xiě)入數(shù)據(jù)時(shí),只有向超過(guò)半數(shù)的 Journal Node 上都寫(xiě)入成功時(shí)才認(rèn)為寫(xiě)入成功。

每當(dāng)客戶端通過(guò) Active NameNode 對(duì) HDFS 進(jìn)行更新操作時(shí),Active NameNode 都會(huì)將此次操作同時(shí)寫(xiě)入本地磁盤(pán)和 QJM 上的 EditLog 文件。而 Standby NameNode 則會(huì)定時(shí)從 QJM 上獲取 EditLog 文件,然后把同步的 EditLog 放到內(nèi)存中的文件系統(tǒng)鏡像中,以保持自身內(nèi)存中的元數(shù)據(jù)跟 Active NameNode 同步。

如果 Active NameNode 向 QJM 寫(xiě)入 EditLog 失敗(也就是沒(méi)有滿足超過(guò)半數(shù)的 Journal Node 返回成功),那么 Active NameNode 會(huì)退出進(jìn)程,然后等待 Standby NameNode 接管后進(jìn)行數(shù)據(jù)恢復(fù)。

Standby NameNode 除了定時(shí)從 QJM 同步 EditLog 之外,還會(huì)定期對(duì)內(nèi)存中的文件系統(tǒng)鏡像做 checkpoint,然后將生成的 FSImage 文件傳給 Active NameNode。Active NameNode 收到 Standby NameNode 發(fā)送的 FSImage 之后,會(huì)將本地舊的 FSImage 文件刪除。

這樣,通過(guò) QJM,主備 NameNode 實(shí)現(xiàn)了元數(shù)據(jù)的同步,那么當(dāng)主備進(jìn)行切換的時(shí)候,他們之間又是如何進(jìn)行交互的呢?

主備切換

當(dāng) Active NameNode 出現(xiàn)故障異常退出的時(shí)候,需要保證在 Standby NameNode 切換成 Active 狀態(tài)后元數(shù)據(jù)與 Active NameNode 保持一致。但是從之前的介紹中可以得知,Standby NameNode 是定時(shí)從 QJM 上獲取 EditLog 文件,那么當(dāng) Active NameNode 出現(xiàn)故障時(shí),Standby NameNode 上的數(shù)據(jù)并不是嚴(yán)格同步的。

同時(shí),當(dāng) Active NameNode 出現(xiàn)故障時(shí),也無(wú)法保證 QJM 上的數(shù)據(jù)是一致的??紤]這樣一種情況,假設(shè) QJM 中有 3 個(gè)節(jié)點(diǎn),Active NameNode 在分別向這三個(gè)節(jié)點(diǎn)發(fā)送完寫(xiě)入命令后崩潰退出了,此時(shí)只有一個(gè) Journal Node 寫(xiě)入成功,而其他兩個(gè) Journal Node 寫(xiě)入失敗。那么此時(shí) QJM 就處于一個(gè)數(shù)據(jù)不一致的狀態(tài),在這種情況下就需要對(duì) QJM 上的數(shù)據(jù)進(jìn)行恢復(fù),使其達(dá)到一致性狀態(tài)。

綜上所述,在發(fā)生主備切換 Standby NameNode 切換為 Active 狀態(tài)后,需要先對(duì) QJM 進(jìn)行數(shù)據(jù)恢復(fù),然后進(jìn)行數(shù)據(jù)同步,只有執(zhí)行完這兩個(gè)操作之后,Standby NameNode 才能對(duì)外提供服務(wù)。

下面對(duì)這兩個(gè)過(guò)程做一個(gè)簡(jiǎn)單的介紹。

QJM 的數(shù)據(jù)恢復(fù)

首先,需要明確的是,數(shù)據(jù)恢復(fù)肯定是發(fā)生在 Standby NameNode 成為 Active 之后。那么在新的 Active NameNode 被選舉出來(lái)之后,需要更新所有 Journal Node 上的 Epoch(可以將 Epoch 理解成每一次主備切換的標(biāo)識(shí)符,是一個(gè)全局唯一的順序遞增的整數(shù))。

其次,需要進(jìn)行數(shù)據(jù)恢復(fù)的肯定是 QJM 上最后一個(gè) EditLog Segment 文件,因?yàn)?Active NameNode 在異常退出前寫(xiě)入的肯定是最新的 EditLog 文件。每個(gè) Journal Node 上最后的 EditLog Segment 的起始事務(wù) id 會(huì)在更新完 Epoch 后返回給 Active NameNode,而 Active NameNode 則是從所有 Journal Node 返回的 Epoch 中選取最大的一個(gè)作為數(shù)據(jù)恢復(fù)的基準(zhǔn)數(shù)據(jù)源。

Active NameNode 將數(shù)據(jù)恢復(fù)的基準(zhǔn)數(shù)據(jù)源所在的 Journal Node 信息發(fā)送給其他所有 Journal Node 之后,其他的節(jié)點(diǎn)會(huì)從該數(shù)據(jù)源所在節(jié)點(diǎn)上下載 EditLog Segment 文件,將本地的文件替換掉。

數(shù)據(jù)同步

在完成了數(shù)據(jù)恢復(fù)的過(guò)程后,此時(shí) QJM 上的數(shù)據(jù)已經(jīng)達(dá)到了一致?tīng)顟B(tài),而且與 Active NameNode 退出前的數(shù)據(jù)一致。此時(shí)新的 Active NameNode 只需要將 QJM 上未同步的 EditLog 文件同步到本地,加載到內(nèi)存中后就可以達(dá)到與舊的 Active NameNode 完全一致的元數(shù)據(jù)狀態(tài)。

而新的 Active NameNode 從 QJM 上同步數(shù)據(jù)的過(guò)程和 Standby NameNode 定時(shí)從 QJM 上同步 EditLog 的實(shí)現(xiàn)是一樣的。

主備切換實(shí)現(xiàn)

在介紹了共享存儲(chǔ)系統(tǒng)之后,下面就可以來(lái)介紹主備 NameNode 在發(fā)生故障切換時(shí)的具體過(guò)程。

NameNode 的主備切換主要由 ZKFailoverController、HealthMonitor 和 ActiveStandbyElector 這三個(gè)組件協(xié)同實(shí)現(xiàn)。

首先簡(jiǎn)單介紹下這三個(gè)組件的作用。

ZKFailoverController

ZKFailoverController 作為 NameNode 上的一個(gè)獨(dú)立進(jìn)程啟動(dòng)(zkfc 進(jìn)程),啟動(dòng)的時(shí)候會(huì)創(chuàng)建 HealthMonitor 和 ActiveStandbyElector 這兩個(gè)線程。ZKFailoverController 在創(chuàng)建了這兩個(gè)線程的時(shí)候,同時(shí)也向 HealthMonitor 和 ActiveStandbyElector 注冊(cè)了相應(yīng)的回調(diào)方法。

HeathMonitor

HealthMonitor 主要負(fù)責(zé)監(jiān)測(cè) NameNode 的健康狀態(tài),如果發(fā)現(xiàn) NameNode 的狀態(tài)發(fā)生了變化,那么會(huì)調(diào)用 ZKFailoverController 的回調(diào)方法進(jìn)行自動(dòng)的主備選舉。

ActiveStandbyElector

ActiveStandbyElector 主要負(fù)責(zé)進(jìn)行自動(dòng)的主備選舉,內(nèi)部封裝了 ZooKeeper 的處理邏輯。一旦 ZooKeeper 上對(duì) NameNode 的主備選舉完成,ActiveStandbyElector 會(huì)調(diào)用 ZKFailoverController 的回調(diào)方法來(lái)進(jìn)行 NameNode 的主備切換。

在介紹完了這三個(gè)組件之后,就可以來(lái)介紹具體的主備切換過(guò)程了。

具體過(guò)程

NameNode 的主備切換過(guò)程大體過(guò)程如下:

  • HealthMonitor 在初始化完成后,會(huì)啟動(dòng)內(nèi)部的線程來(lái)定時(shí)監(jiān)測(cè) NameNode 的健康狀態(tài)。
  • HealthMonitor 如果發(fā)現(xiàn) NameNode 的狀態(tài)發(fā)生了改變,則會(huì)回調(diào) ZKFailoverController 注冊(cè)的方法進(jìn)行處理。
  • 如果 ZKFailoverController 判斷需要進(jìn)行主備切換,則會(huì)使用 ActiveStandbyElector 來(lái)進(jìn)行自動(dòng)的主備選舉。
  • ActiveStandbyElector 與 ZooKeeper 進(jìn)行交互,完成自動(dòng)的主備選舉。
  • ActiveStandbyElector 在完成主備選舉后,會(huì)回調(diào) ZKFailoverController 注冊(cè)的方法,通知 ZKFailoverController 當(dāng)前的 NameNode 成為主或備。
  • ZKFailoverController 在接收到 ActiveStandbyElector 的通知后調(diào)用對(duì)應(yīng) NameNode 的接口,將 NameNode 轉(zhuǎn)換為 Active 或 Standby 狀態(tài)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容