傳統的HDFS機制如下圖所示:
也就是存在一個NameNode,一個SecondaryNameNode,然后若干個DataNode。這樣的機制雖然元數據的可靠性得到了保證(靠edits,fsimage,meta.data等文件),但是服務的可用性並不高,因為一旦NameNode出現問題,那么整個系統就陷入了癱瘓。所以,才引入了HDFS的HA機制。我們先來看一下關於HDFS的HA機制和Federation機制的簡介:
HA解決了HDFS的NameNode的單點問題;
Federation解決了整個HDFS集群中只有一個名字空間,並且只有單獨的一個NameNode管理所有DataNode的問題。
一、HA機制(High Availability)
1.HA集群
HDFS 的高可用性(HA, High Availability)是為了解決集群不可用的問題引入的,集群不可用主要是宕機、 NameNode 軟硬件升級等導致的。 HA 機制通過提供選擇運行在同一集群中的一個熱備用的“主/備”兩個冗余 NameNode ,使得在機器宕機或維護的過程中可以快速轉移到另一個 NameNode。
典型的 HA 集群會配置兩個獨立機器為 NameNode ,分別為主 NameNode 和副本 NameNode 。正常情況下,主 NameNode 為 alive 狀態而副本 NameNode 為休眠狀態,活動 NameNode 負責處理集群中所有的客戶端操作,待機時僅僅作為一個 slave ,保持足夠的狀態,如果有必要會提供一個快速的故障轉移。
關於保持同步。為了保持備用節點與活動節點狀態的同步,兩個節點同時訪問一個共享存儲設備(例如從 NAS、NFS 掛載)到一個目錄。
2.HA機制作用
HA 機制出現的作用主要是為了:
1.解決單點故障;
2.提升集群容量和集群性能。
二、Federation機制
為了防止單點失效(Single PointFailure),在 NameNode 只有命名空間的情況下。其最主要的原因是對 HDFS 系統的文件隔離,Federation 可以解決大部分單 NameNode HDFS 的問題。
總之,HDFSFederation就是使得HDFS支持多個命名空間,並且允許在HDFS中同時存在多個NameNode。
1.Federation架構
HDFS Federation使用多個獨立的 NameNode / NameSpace 使得 HDFS 的命名服務能水平擴展,HDFS Federation中的 NameNode 之間為獨立且不需要相互協調,Federation 中的 NameNode 提供了名字空間和塊管理功能。Federation 中的 DataNode 被所有的 NameNode 用作公共存儲塊的地方。每個 DataNode 都會向所在集群中所有的 NameNode 注冊,並且周期性發送心跳和塊信息報告,同時處理來自 NameNode 的指令。
HDFS 只有一個名字空間 NameSpace 時,它使用全部的塊,而 Federation HDFS 中有多個獨立的NameSpace ,並且每個名字空間使用一個塊池Block Pool(注:就是屬於單個名字空間的一組 Block ),每個DataNode 為所有的塊池存儲塊,DataNode是個物理概念,而塊池是另一個重新將塊划分的邏輯概念。
HDFS 中只有一組塊。而Federation HDFS中有多組獨立的塊,塊池就是屬於同一個名字空間的一組塊。
HDFS 由一個 NameNode 和一組 DataNode 組成,而 Federation HDFS 由多個 NameNode 和一組 DataNode 組成,每個 DataNode 會為多個塊池存儲塊。同一個 DataNode 中可以存着屬於多個塊池的多個塊。塊池允許一個名字空間在不通知其他名字空間的情況下為一個新的 Block 創建 Block ID ,同時一個 NameNode 失效不會影響其下的 DataNode 為其他的 NameNode 服務。
在 HDFS 中,所有的更新、回滾都是以 NameNode 和 Block Pool 為單元發生的,即同 HDFS Federation 中不同的 NameNode/Block Pool 之間沒有什么關系。
在 DataNode 中,對應於每個 NameNode 都有一個相應的線程。每個 DataNode 會去每個 NameNode 注冊,並周期性地給所有的 NameNode 發送心跳和使用報告,DataNode 還會給 NameNode 發送其所在的塊池報告 block report,由於有多個 NameNode 同時存在,因此任何一個 NameNode 都可以隨時動態加入、刪除和更新。
2.多名字空間管理
在一個集群中需要唯一的名字空間還是多個名字空間,核心問題是名字空間中數據的共享和訪問的問題。解決數據共享和訪問的一種方法:使用全局唯一的名字空間,在多個名字空間下,還可以使用 Client Side Mount Table 方式做到數據共享和訪問。
HDFS Federation 名字空間管理基本原理:將各個名字空間掛載到全局 mount-table 中,就可以將數據到全局共享;同樣,名字空間掛載到個人 mount-table 中,就成為應用程序可見的名字空間視圖。
而HA架構圖如下圖所示:
我們需要兩台NameNode,那么我們就需要保證信息的同步,因為前面介紹HDFS時講過,edits日志里面總是存儲最新的數據,所以我們就讓edits共享,兩台NameNode每次都往同一個edits里面進行讀寫。但是只有一個edits,難免會出問題,所以我們就同時有多個edits,並把他們部署到集群上。多個,又部署到集群上,肯定會涉及數據同步,切換等多個問題,這不就是之前我們討論的Zookeeper問題嗎?所以我們做了一個分布式應用qjournal,並用它管理這么多edits,每個edits又叫做journalnode。qjournal底層是基於Zookeeper實現的,所以journalnode只要有半數以上的節點活着,qjournal就不會癱瘓。
兩台NameNode不能同時處於active狀態,一台處於active狀態,另外一台就必須是standby狀態。當一台NameNode死了,另外一台就會變成active狀態了。但是兩台NameNode之間的切換是怎么保證的呢?
這里開了兩個進程,時時刻刻監控本地NameNode的狀態。當前active狀態的NameNode的進程如果發現不正常,就往zookeeper里面寫一些數據。另外一個進程時時刻刻從zookeeper里面讀數據,來隨時掌握
對方NameNode的狀態,如果發現對方死了,就可以進行NameNode的切換,這個狀態管理的進程就叫做zkfc。用來做兩個NameNode的切換管理,包括失敗切換。具體功能依賴於zookeeper實現。
這里還有一個問題,就是brain split:
所謂brain split,就是一台NameNode出現假死,而另外一台NameNode以為它真死了,所以也變成active了,等一下假死的NameNode恢復了,這樣就會兩台NameNode都處於active狀態,顯然這是不可以的。
我們有兩個解決辦法:
1.ssh發送kill指令,直接殺死對方NameNode進程,再進行切換。
2.ssh指令不能保證每次都執行成功,那就設置一個時間,如果一定時間ssh指令還沒有返回值,就會運行自定義的腳本,將對方NameNode殺死,再進行切換。
這種解決的機制叫做fencing機制。
我們將上面一對NameNode叫做一個nameservice,訪問它可以用ns1(name service 1)來表示。若干個這樣的NameNode對叫做Federation。
這里需要提醒一下:不光HDFS有高可用,YARN也有高可用,只不過相對HDFS就簡單多了,ResourceManager主從切換即可。
最后,介紹一下namenode的安全模式: