喜歡一我的,能夠爲TA作任何事,獲得不接受卻依然心甘情願鞍前馬後,苦苦等候那一線但願。對,這就是備胎,掛在汽車背後,可能一生也用不到的那個圓圈狀的玩意兒,大部分狀況下,它都會默默地掛在那裏,等待幾千分之一的機會,有個倒黴的輪子兄弟出事了,因而它就能派上用場了……(摘自豆瓣)html
在Hadoop的分佈式文件系統HDFS中,NameNode用來保存文件系統的元數據(包含目錄結構/數據塊位置等),若是NameNode上的數據丟失,HDFS上對應的文件數據就沒法找回來了。Hadoop在2.0.0以前的版本,使用SecondaryNameNode備份NameNode的數據,但SecondaryNameNode沒法轉成NameNode,若是NameNode掛了,整個HDFS就會掛掉,沒法實現真正的failover。這篇博文總結了5種Hadoop HA(High Available,高可用)方案,Hadoop2以後官方引入了QJM(Quorum Journal Manager)和NFS用於NameNode的備份和切換。本方將介紹的是QJM方案,它使用第二個NameNode實時同步當前NameNode的數據,相比於SecondaryNameNode,他能夠隨時切換成爲真正的NameNode(一個可轉正的高級備胎)。node
先看看沒有HA的HDFS的系統架構(用draw.io畫的,尼馬這麼好的網站也被牆了):web
而後有HA方案的系統架構:apache
如下的實驗基於4個節點的Hadoop集羣。其中每一個節點的運行的進程列表以下:bootstrap
Role\Host | hd1 | hd2 | hd3 | hd4 |
---|---|---|---|---|
NN | √ | √ | ||
DN | √ | √ | √ | |
JN | √ | √ | √ | |
ZK | √ | √ | √ |
實驗環境中,全部節點的運行環境基本相同:bash
下面是實現這個系統的流程(官方文檔+我的註解+輔助Shell命令)。架構
嚴格按照單節點搭建和集羣搭建兩個步驟,系統建起來徹底沒壓力。我遇到的問題是剛開始在配置文件(salves和core-site.xml等文件)中使用的是ip地址而非主機名,而後在log文件裏看到各類沒法鏈接。解決方案是修改主機名並在hosts文件裏創建映射關係。app
hostname {new_hostname} # 修改主機名,只有當前Session有效 sudo vi /etc/hostname # 永久修改主機名的方法
另外,對於64位的系統,最好從新編譯源碼。ssh
hdfs-site.xml文件:分佈式
<configuration> <property> <name>dfs.namenode.name.dir</name> <value>/data/hadoop/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/data/hadoop/datanode</value> </property> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>hd1:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>hd3:8020</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>hd1:50070</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>hd3:50070</value> </property> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hd1:8485;hd2:8485;hd4:8485/mycluster</value> </property> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/hduser/.ssh/id_rsa</value> </property> <property> <name>dfs.journalnode.edits.dir</name> <value>/data/hadoop/journalnode</value> </property> </configuration>
nameservices
是集羣的命名空間,即便有多個集羣,能夠共用配置文件,可是要注意某些配置項的順序。dfs.ha.namenodes.mycluster
中的mycluster是能夠任取的,可是要和dfs.nameservices
對應。dfs.namenode.rpc-address.mycluster.nn1
參考上一條。dfs.namenode.shared.edits.dir
值的格式是"qjournal://host1:port1;host2:port2;host3:port3/journalId",用來指定對應的JN節點,journalId
建議使用和nameservices
相同的名稱。dfs.client.failover.proxy.provider.mycluster
指定激活NameNode的Java類,目前Hadoop內置的只有上面那個。dfs.ha.fencing.methods
是來用來隔離失效的NameNode的方法,有sshfence
和Shell兩種方式。sshfence
須要配置dfs.ha.fencing.ssh.private-key-files
私鑰文件,以便交互的過程不須要輸入密碼。dfs.journalnode.edits.dir
是JN保存數據的文件。core-site.xml文件:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> </configuration>
mycluster
要和dhfs-site.xml中的dfs.nameservices
對應。fs.defaultFS
不用端口號。改好配置文件好,就要將配置文件同步到全部的機器上了。能夠用rsync將文件同步到多臺機器上。rsync是一個增量同步工具,須要先安裝。下面的rsync.sh的功能是將當前目錄的全部文件發送到文件或參數對應的機器上。
$ cat rsync.sh #! /bin/bash dir=`pwd` pdir=`dirname $dir` send(){ echo "Sending to $2:$1" rsync -avez -e ssh $1 $2:$3 } mul_send(){ while read host do send $dir $host $pdir done < $1 } [ -f $1 ] && mul_send $1 || send $dir $1 $pdir
將rsync.sh放在etc/hadoop目錄下,進入目錄運行
chmod +x rsync.sh ./rsync.sh slaves # or ./rsync.sh hostname
發送完文件以後,就是啓動系統。步驟以下:
在全部JournalNode上運行
sbin/hadoop-daemon.sh --script hdfs start journalnode
在原NameNode上運行
bin/hadoop --script hdfs start namenode # NameNode須要已經format。
(使用上面的rsync.sh文件)將原NameNode(nn1)上的數據複製到第二個NameNode(nn2)。而後在nn2上運行:
bin/hdfs namenode -bootstrapStandby
在NameNode上運行
sbin/start-dfs.sh
上面的NameNode默認以standby的狀態啓動,這時由於沒有active的NameNode,因此是不能在HDFS讀寫文件,須要將其中的一個轉成active狀態。好比將nn1(對應前面的配置)轉成Active:
bin/hdfs haadmin -transitionToActive nn1
而後在NameNode的web頁面上部的括號裏的standby變成active。
轉成standby的命令是:
bin/hdfs haadmin -transitionToStandby nn1
在當前NameNode不能使用時自動切換到第二個NameNode上,須要藉助於ZooKeeper(ZK)。
ZK的安裝過程和Hadoop差很少,就是下載文件、修改配置、複製到全部機器、啓動。具體步驟在這裏。
配置文件conf/zoo.conf:
tickTime=2000 dataDir=/data/hadoop/zookeeper clientPort=2181 initLimit=5 syncLimit=2 server.1=hd2:2888:3888 server.2=hd3:2888:3888 server.3=hd4:2888:3888
hd2,hd3,hd4是主機名,至少須要三臺,這個在一臺機掛了整個系統還能用,ZK的數量通常是奇數。
而後要在hdfs-site.xml上添加配置:
<property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <property> <name>ha.zookeeper.quorum</name> <value>hd2:2181,hd3:2181,hd4:2181</value> </property>
而後就是在NameNode的機器上初始化NameNode在ZK的狀態了:
bin/hdfs zkfc -formatZK
重啓HDFS或手動啓動DFSZKFailoverController(ZKFC):
sbin/stop-dfs.sh # 重啓hdfs sbin/start-dfs.sh sbin/hadoop-daemon.sh start zkfc # 啓動ZKFC
在該HA方案中,每個NameNode都有一個對應的ZKFC。ZKFC會隨NameNode啓動。
在當前NameNode運行jps
看NameNode的進程ID,而後kill掉。經過Web頁面(http://hdx:50070),能夠看到standby的NameNode幾乎在kill的同時轉成active了。