HDFS 09 - HDFS NameNode 的高可用機制

瘦風發表於2021-08-22

1 - 為什麼要高可用

在 Hadoop 中,NameNode 扮演著至關重要的角色 —— 整個 HDFS 檔案系統的後設資料資訊都由 NameNode 管理,一旦 NameNode 程式出現異常,或者維護 NameNode 所在節點的時候,都會導致 HDFS 叢集不可用。

所以 NameNode 的可用性直接決定了 Hadoop 叢集的可用性。

2 - NameNode 的高可用發展史

在 Hadoop 2.0 以前,每個 HDFS 叢集只有一個 NameNode,一旦這個節點不可用,則整個 HDFS 叢集將處於不可用狀態 —— 即,HDFS 2.0 以前,NameNode 存在單點故障風險。

與典型的 HA(High Availability,高可用)方案一樣(參考:常見的六種容錯機制),HDFS 2.0 開始支援的 HA,就是 在 HDFS 叢集中同時執行兩個 NameNode

一個處於 Active(活躍)狀態:負責叢集中所有客戶端的操作(修改名稱空間、刪除備份資料塊等操作);

另一個處於 Standby(備份)狀態:充當從伺服器,和 Active NameNode 有相同的名稱空間和後設資料。

當 Active NameNode 停止服務時,Standby NameNode 能夠快速進行故障切換,以保證 HDFS 叢集服務不受影響。

3 - HDFS 的高可用架構

看圖:

HDFS 09 - HDFS NameNode 的高可用機制

Standby NemeNode 是如何做到故障切換的?換句話說,它和 Active NameNode 之間的資料是如何保持一致的?

3.1 Standby 和 Active 的名稱空間保持一致

它們儲存著一樣的後設資料,可以把叢集恢復到系統奔潰時的狀態 —— 這是實現自動故障切換的基礎。

為了使備份節點與活動節點的資料保持同步,兩個節點都需要同一組獨立執行的節點來通訊,HDFS 中把這樣的節點稱為 JournalNode。

1)第一關係鏈的一致性,即 Active NameNode 和 Standby NameNode 的名稱空間狀態的一致性:

a)Active NameNode 會定期地把 修改名稱空間或刪除備份資料塊等操作 記錄到 EditLog,同時寫到 JN 的多數節點中。

b)Standby NameNode 會一直監聽 JN 上 EditLog的變化,如果 editlog 有改動,Standby NameNode 就會讀取 editlog 並與當前的名稱空間合併。

c)Active NameNode 出現故障時,Standby NameNode 會保證已經從 JN 上讀取了所有 editlog 並與名稱空間合併,然後才會從 Standby 切換為 Active。

2)第二關係鏈的一致性,即資料塊的儲存資訊的一致性:

為了使故障切換能夠儘快執行成功,就要保證 Standby NameNode 也 實時儲存了資料塊的儲存資訊,HDFS 中是這樣做的:

DataNode 會同時向兩個 NameNode 傳送心跳以及塊的儲存資訊。

這樣以來,發生故障切換時,Standby NameNode 就可以直接切換到 Active 狀態(它和舊 Active 節點的後設資料完全一致),而不需要等待所有的 DataNode 彙報全量資料塊資訊 —— 這也是熱備功能。

需要注意:Standby NameNode 只會更新資料塊的儲存資訊,並不會向 DataNode 傳送複製或刪除資料塊的指令,這些指令只能由 Active NameNode 傳送。

3.2 同一時刻只有一個 Active NameNode

如果兩個 NameNode 都是活躍狀態,那麼這個叢集就會被分成2個小叢集,它們都認為自己是唯一活動的叢集。這就是著名的“腦裂”現象。

腦裂的 HDFS 叢集很可能造成資料錯亂、丟失資料塊,還可能向 DataNode 下發錯誤的指令,這些錯誤都很難恢復。

4 - HDFS 高可用的實現原理

這裡主要介紹通過隔離(fencing)Quorum Journal Manager(QJM)共享儲存實現的 HDFS 高可用。

4.1 隔離(Fencing)- 預防腦裂

預防腦裂的常見方案就是 Fencing,即隔離,思路是把舊的 Active NameNode 隔離起來,使它不能正常對外提供服務,使叢集在任何時候都只有一個 Active NameNode。

HDFS 提供了 3 個級別的隔離(Fencing):

1)共享儲存隔離:同一時間只允許一個 NameNode 向 JournalNode 寫入 EditLog 資料。

QJM中每一個JournalNode中均有一個epochnumber,匹配epochnumber的QJM才有許可權更新 JN。當 Namenode 由 standby 狀態切換成 active 狀態時,會重新生成一個 epochnumber,並更新 JN 中的 epochnumber,以至於以前的 Active Namenode 中的QJM 中的 epoch number 和 JN 的 epochnumber 不匹配,故而原 Active Namenode上的 QJM 沒法往 JN 中寫入資料(後面會介紹原始碼),即形成了 fencing。

2)客戶端隔離:同一時間只允許一個 NameNode 可以響應客戶端的請求。

3)DataNode 隔離:同一時間只允許一個 NameNode 向 DataNode 下發名稱空間相關的命令,例如刪除塊,複製塊等。

4.2 Qurom Journal Manager 共享儲存

在 HDFS 的 HA 架構中還有一個非常重要的部分:Active NameNode 和 Standby NameNode 之間如何共享 EditLog 檔案。

解決思路是:Active NameNode 將日誌檔案寫到共享儲存上,Standby NameNode 實時地從共享儲存讀取 EditLog 檔案,然後合併到 Standby NameNode 的名稱空間中。一旦 Active NameNode 發生錯誤,Standby NameNode 就可以立即切換到Active狀態。

HDFS 2.6 開始,提供了一個叫做 Qurom Journal Manager(QJM)的共享儲存方案,來解決 HA 架構中後設資料的共享儲存問題。

QJM 基於 Paxos 演算法實現,基本原理是:HDFS 叢集中有 2n+1 臺 JournalNode,EditLog 儲存在 JN 的本地磁碟上;

每個 JournalNode 都允許 NmaeNode 通過它的 RPC 介面讀寫 EditLog 檔案;

當 NmaeNode 向共享儲存寫入 EditLog 檔案時,它會通過 QJM 向叢集中所有的 JournalNode 並行傳送寫 EditLog 檔案的請求,當有一半以上(>=n+1)的 JN 返回寫操作成功時,就認為這次寫操作成功了。

每次寫資料操作有多數(>=n+1)JN 返回成功,就認為這次寫操作成功了。

由此我們可以知道,這個 QJM 必須也是高可用的,否則 HDFS 的高可用就無法保障。

QJM 實現 HA 的主要好處:

  • 不存在單點故障問題;
  • 不需要配置額外的共享儲存,降低了複雜度和維護成本;
  • 不需要單獨配置 Fencing 實現(見文末#5.1節),因為 QJM 本身就內建了 Fencing 的功能;
  • 系統的魯棒性程度是可配置的( QJM 基於 Paxos 演算法,配置 2n+1 臺 JournalNode,最多能容忍 n 臺機器同時掛掉);
  • QJM 中儲存日誌的 JournalNode 不會因為其中一臺的延遲而影響整體的延遲,而且也不會因為 JournalNode 的數量增多而影響效能(因為 NameNode 向 JournalNode 傳送日誌是並行的)。

關於 QJM 的具體工作原理,後面有機會了專門講講。

5 - 其他補充

5.1 QJM 的 Fencing 方案

QJM 的 Fencing 只能讓原來的 Active NN 失去對 JN 的寫許可權,但是原來的 Active NN 還是可以響應客戶端的請求,對 DataNode 進行讀操作。

對客戶端和 DataNode 的隔離是通過配置 dfs.ha.fencing.methods 實現的,Hadoop 公共庫中有兩種 Fencing 實現:

shell:即執行一個使用者事先定義的 shell 命令或指令碼來完成隔離。

sshfence:ssh 到原 Active NN 上,使用 fuser 結束程式(通過 TCP 埠號定位程式 pid, jps 命令更準確)。

5.2 - HDFS 高可用元件簡介

ZKFailoverController

是基於 ZooKeeper 的故障轉移控制器,它負責控制 NameNode 的主備切換,ZKFailoverController 會監測NameNode 的健康狀態,當發現 Active NameNode 出現異常時會通過 ZooKeeper 進行一次新的選舉,完成 Active 和 Standby 狀態的切換。

HealthMonitor

週期性呼叫 NameNode 的 HAServiceProtocol RPC 介面(monitorHealth 和 getServiceStatus),監控NameNode 的健康狀態並向 ZKFailoverController 反饋。

ActiveStandbyElector

接收 ZKFailoverController 的選舉請求,通過 ZooKeeper 自動完成主備選舉,選舉完成後回撥ZKFailoverController 的主備切換方法對 NameNode 進行 Active 和 Standby 狀態的切換。

參考資料

https://hadoopdoc.com/hdfs/hdfs-namenode-ha

https://blog.csdn.net/u012736748/article/details/79534019


版權宣告

作者:瘦風(https://healchow.com)

出處:部落格園-瘦風的南牆(https://www.cnblogs.com/shoufeng)

感謝閱讀,公眾號 「瘦風的南牆」 ,手機端閱讀更佳,還有其他福利和心得輸出,歡迎掃碼關注?

HDFS 09 - HDFS NameNode 的高可用機制

本文版權歸博主所有,歡迎轉載,但 [必須在頁面明顯位置標明原文連結],否則博主保留追究相關人士法律責任的權利。

相關文章