hadoop 2.0.0以前,namenode存在單點故障問題(SPOF,single point of failure),若是主機或進程不可用時,整個集羣就變得不可用,直到namenode進行重啓或產生新的namenode。主要有兩種方式會影響到HDFS集羣:java
HDFS的高可用特性解決了以上兩個問題,經過在一個集羣中運行兩個冗餘的Namenode,分別以active/passiave配置方式實現一個熱備處理。這容許namenode宕機後可以快速容災到新節點,或者管理員以優雅的方式進行計劃性運維容災處理。node
在電信的HA集羣中,配置兩臺獨立的主機爲namenode。任什麼時候刻,只有一臺主機處於active狀態,另外一臺爲standby狀態。active節點負責集羣中全部客戶端的操做,standby節點只是扮演一個從屬的角色,他會維護足夠多的狀態信息進行必要條件下的快速容災處理。web
爲了讓standby節點同active節點保持狀態同步,兩個節點都須要同一組稱之爲「JournalNode」的進程通訊。當active節點對名字空間進行了修改後,都會記錄這條修改記錄到JN節點的半數以上節點。Standby節點便可從JN節點上讀取這些編輯日誌,Standby節點不斷觀察編輯日誌的修改行爲,若是有修改動做發生,便會馬上應用到本身的名字空間中。容災發生時,standby節點在切換到active狀態前要確保從JN上讀取了全部的修改動做。這能夠保證在容災發生前,名字空間的狀態是徹底同步的。shell
爲了提供快速容災,讓Standby節點擁有最新的block位置信息也是很是有必要的。爲了作到這一點,須要使用兩個namenode位置對Datanode進行配置,而且datanode會同時發送block信息和心跳信息給兩個namenode。apache
正確操做HA集羣的一個重點事項就是同一時刻只有一個namenode處於active狀態,不然,名字空間狀態很快在二者之間產生誤差,從而致使數據丟失或不一致的風險。爲了確保這一屬性並防止所謂的「腦裂場景」,JournalNode節點只容許同一時刻一個namenode進行寫入。容災期間,成爲active的namenode只是接管journalNode的寫操做,有效防止其餘的namenode節點,容許新的active節點安全處理容災工做。bootstrap
爲了部署HA集羣,須要作以下準備:centos
namenode主機安全
運行active和standby的namenode主機,他們具備相同的硬件配置,這種相同的硬件配置也會用在非HA集羣下。session
Journalnode主機架構
運行journalnode節點的主機。journalnode進程是輕量級進程,所以能夠和他其餘hadoop守護進程並存,例如namenode、resourcemanager等。注意:必須至少配置3個Journalnode守護進程,由於編輯日誌必需要寫入JN的半數以上。這容許系統容忍一臺journalnode節點掛掉。爲增長系統的容災能力,應該運行奇數個journalnode節點,例如3,5,7臺。當運行n個journalnode節點時,最多容忍(n - 1)/ 2節點故障。
注意,在HA集羣模式下,standby節點也會對名字空間狀態進行檢查點操做,所以沒有必要運行secondary namenode,checkpointnode或BackupNode。實際上,這樣作會致使錯誤,這也運行經過改造非HA模式下的secondaryNode成爲HA模式。
HA配置是向後兼容的,容許現有的namenode配置不作修改就能夠工做。集羣中全部節點具備相同的配置,而不須要個不一樣主機依據節點類型進行不一樣的配置。
HA集羣使用nameservice id區分一個HDFS實例,他能夠包含多個HA的namenode節點。集羣中的Namenode使用惟一的namenode ID進行區分。爲了對全部節點使用一個配置文件,配置可使用nameservice ID和namenode ID做爲後綴。
配置HA Namenode,須要添加幾個選項給hdfs-site.xml配置文件。
這些選項的順序並不重要,可是dfs.nameservices 和dfs.ha.namenodes.[nameservice ID]值很關鍵,所以配置前須要肯定這些值的內容。
dfs.nameservices
名稱服務的邏輯名,該名稱是任意的,將會用於配置和HDFS路徑的受權。
<property> <name>dfs.nameservices</name> <value>mycluster</value> </property>
dfs.ha.namenodes.[nameservice ID]
名稱服務中每一個namenode的惟一標識。使用「,」號分割的名稱列表,datanode經過他來檢測集羣中的全部namenode。
<property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property>
注意:目前最多隻支持兩個名稱節點。
dfs.namenode.rpc-address.[nameservice ID].[name node ID]
配置每一個名稱節點的IPC端口,須要在單獨的元素進行配置。
<property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>s101:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>s102:8020</value> </property>
dfs.namenode.http-address.[nameservice ID].[name node ID]
配置每一個namenode的http監聽地址。
<property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>s101:50070</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>s102:50070</value> </property>
dfs.namenode.shared.edits.dir
namenode從JNs集合上讀寫日誌的uri地址。
<property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://s102:8485;s103:8485;s104:8485/mycluster</value> </property>
dfs.client.failover.proxy.provider.[nameservice ID]
容災代理提供商類,用來檢測哪一個namenode是active狀態,哪一個namenode用來服務於客戶端請求。當前hadoop只有一個實現。
<property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha .ConfiguredFailoverProxyProvider</value> </property>
dfs.ha.fencing.methods
容災期間防禦namenode的java類或者腳本列表。使用QJM(Quorum journal manager)時只容許一個namenode向journalnodes寫入數據,所以不存在由於腦裂損壞系統元數據的可能。可是,容災發生時,依然有可能的是上一個active節點向客戶端提供讀請求服務,直到向JN節點寫入數據失敗形成namenode中止後致使的時間過時。基於這一緣由,使用QJM時仍有必要配置一些防禦方法。爲提高系統在防禦事件失敗時的可用性,建議配置防禦方法確保列表中最後一個防禦方法返回成功。注意若是選擇使用並沒有實際的防禦方法,也要進行一些配置,好比「shell(bin/true)」等。
防禦方法能夠配置成列表,而後按序調用直到防禦方法成功爲止。hadoop給出了兩種方式:shell和sshfence。自定義防禦方法能夠實現org.apache.hadoop.ha.NodeFencer類。
防禦方法配置成多行列表的形式,容災時按順序進行調用直到防禦方法返回成功爲止。hadoop有兩種方式:shell和sshfence。自定義的話能夠實現org.apache.hadoop.ha.NodeFencer類。
sshfence方式是ssh到active的namenode節點並將進程殺死,該中方式必須可以無密登陸到目標節點,所以必需要配置私鑰(dfs.ha.fencing.ssh.private-key-files )選項,能夠配置成逗號分隔的多個私鑰列表,配置方式以下:
<property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/centos/.ssh/id_rsa</value> </property>
shell方式是運行一個shell腳原本防禦active namenode。配置方式以下:
<property> <name>dfs.ha.fencing.methods</name> <value>shell(/path/to/my/script.sh arg1 arg2 ...)</value> </property>
fs.defaultFS
hadoop文件系統客戶端沒有指定前綴時使用的默認路徑前綴。
<property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property>
dfs.journalnode.edits.dir
Journanode守護進程存放本地狀態的路徑,該路徑使用絕對路徑,使用一個路徑便可。
<property> <name>dfs.journalnode.edits.dir</name> <value>/path/to/journal/node/local/data</value> </property>
配置完成後,必須在JN節點啓動全部的JN守護進程,可以使用以下命令完成:
hadoop-daemon.sh start journalnode
一旦JN進程啓動完成,必需要對兩個HA的namenode節點的磁盤元數據進行初始同步
若是搭建的是全新的hdfs集羣,應該在其中的一個namenode上運行以下命令進行格式化
hdfs namenode -format
若是已經格式化過namenode或者轉換非HA模式到HA模式下,須要複製namenode的元數據目錄到另外一個namenode相同目錄下,未格式化的namenode節點運行以下命令,完成待命狀態引導。該命令還會保證jn節點包含足夠多了編輯動做,以便可以啓動兩個namenode節點。
hdfs namenode -bootstrapStandby
若是正在將非HA模式轉換成HA,你應該運行以下命令,將會從本地namenode的編輯日誌初始化到JN節點的編輯數據。
hdfs namenode -initializeSharedEdits
此時能夠像以往啓動namenode同樣啓動兩個namenode。同時,能夠分別使用兩個namenode各自的webui地址查看各自的狀態。你會發現兩臺namenode的狀態都是standby。
http://s101:50070 http://s105:50070
配置並啓動namenode後,就能夠進行管理工做,可使用以下管理命令對namenode進行管理:
Usage: haadmin [-transitionToActive <serviceId>] [-transitionToStandby <serviceId>] [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>] [-getServiceState <serviceId>] [-checkHealth <serviceId>] [-help <command>]
transitionToActive和transitionToStandby
切換狀態到active或standby狀態,這些命令不會進行防禦處理,儘可能少使用,而是用使用failover代替。
failover
在兩個namenode間進行容災演練,從第一個nn到第二個nn進行容災處理,若是第一個nn是standby,就將第二個nn變換成active態。若是第一個是active,首先嚐試優雅變換到standby狀態。若是這一個過程失敗,就按序執行防禦方法直到成功,此過程事後,第二個nn纔會變成active態。若是防禦方法都沒有成功,則第二個nn就不會變成active態並返回一個錯誤。
getServiceState
檢測指定的nn的狀態,鏈接到namenode檢測其狀態,打印active或standby字樣。
checkHealty
檢查給定namenode的健康情況,namenode本省可以執行一個診斷工做,包括檢查是否內部服務在進行,若是健康返回0,不然返回非0。
注意該命令還未實現,始終返回0,除非namenode徹底中止。
以上部分描述瞭如何配置手動容災,在該模式下,系統沒法自動觸發容災處理,哪怕是active掛掉。本章描述如何配置自動容災。
自動容災引入兩個新組件:一個是Zookeeper的quorum,一個是ZKFailoverController進程(簡稱zkfc)。
apache zookeeper是高可用服務用於維護少許協同數據,通知客戶端數據變動、監控客戶端故障。自動容災依賴zookeeper一下內容:
故障檢測
集羣中每一個namenode主機都在zookeeper中維護了永久session。若是機器宕機,session就會超時,通知其餘namenode觸發容災。
active namenode選舉
zookeeper提供一種簡單機制可以以獨佔方式選舉一個node爲active。若是當前active節點宕機,另外一個namenode就會接管一個排他鎖代表本身將成爲下一個active。
zkfc是zookeeper客戶端管理監控namenode狀態的新組件。每一個運行namenode主機都會運行一個zkfc進程。zkfc進程負責以下工做:
監控檢查
zkfc週期性ping本地namenode的狀態,若是namenode可以及時響應,則認爲namenode是健康的。若是node宕機或進入某種不監控狀態,監控器就標記其位不健康狀態。
zk session管理
若是本地namenode是健康的,zkfc會持有zk的session。若是namenode是健康的,zkfc還會持有一把臨時鎖。若session過時,lock節點將會被刪除。
基於zk的選舉
若是namenode是健康的,zkfc就會知道不會有其餘人持有lock節點,本身就會嘗試上鎖。如若成功就贏得選舉,並運行容災程序,本地namenode就成爲active狀態。
典型配置zookeeper模式是使用3或5個節點,因爲zookeeper是輕量級的,所以能夠和其餘進程位於同一主機,例如namenode或datanode。許多人選擇部署第三節點在ResourceManager主機上。建議配置zookeeper在單獨的磁盤驅動器上存儲數據,同hdfs元數據分開,以得到更好的性能和隔離處理。搭建zookeeper集羣請參考相關文章,這裏不作介紹。
中止hdfs集羣。
在hdfs-site.xml文件中添加以下配置啓用自動容災。s
<property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
在core-site.xml文件中添加zk節點地址。
<property> <name>ha.zookeeper.quorum</name> <value>s102:2181,s103:2181,s104:2181</value> </property>
在其中的一個namenode節點上運行以下命令:
hdfs zkfc -formatZK
該命令會在zk中建立相應節點存儲用於容災的數據。
因爲已經啓用了自動容災,所以啓動namenode時,會自動啓動zkfc進程,並自動選舉一個namenode爲active節點。
也能夠手動啓動zkfc進程,運行以下命令:
$>hadoop-daemon.sh start zkfc