Hadoop的HA機制(Zookeeper叢集+Hadoop叢集)配置記錄
博主:hadoop_version=2.4.1
java_version=1.7
zooKeeper_version=3.4.5
Linux =CentOs 6.5
1.首先說明HA是什麼?
HA意為High Available,高可用性叢集,是保證業務連續性的有效解決方案,一般有兩個或兩個以上的節點,且分為活動節點及備用節點。通常把正在執行業務的稱為活動節點,而作為活動節點的一個備份的則稱為備用節點。當活動節點出現問題,導致正在執行的業務(任務)不能正常執行時,備用節點此時就會偵測到,並立即接續活動節點來執行業務。從而實現業務的不中斷或短暫中斷。
2.HA機制的前世今生
2.1 Hadoop_1.X叢集的NameNode
Namenode 管理者檔案系統的Namespace。它維護著檔案系統樹(filesystem tree)以及檔案樹中所有的檔案和資料夾的元資料(metadata)。管理這些資訊的檔案有兩個,分別是Namespace 映象檔案(Namespace image)和操作日誌檔案(edit log),這些資訊被Cache在RAM中,當然,這兩個檔案也會被持久化儲存在本地硬碟。Namenode記錄著每個檔案中各個塊所在的資料節點的位置資訊,但是他並不持久化儲存這些資訊,因為這些資訊會在系統啟動時從資料節點重建。
在hadoop1時代,只有一個NameNode。如果該NameNode資料丟失或者不能工作,那麼整個叢集就不能恢復了。這是hadoop1中的單點問題,也是hadoop1不可靠的表現。如下圖所示,便是hadoop1.0的架構圖;
2.2 Hadoop_2.x叢集的NameNode
為了解決hadoop1中的單點問題,在hadoop2中新的NameNode不再是隻有一個,可以有多個(目前只支援2個(2.4.1版本))。每一個都有相同的職能。一個是active狀態的,一個是standby狀態的。當叢集執行時,只有active狀態的NameNode是正常工作的,standby狀態的NameNode是處於待命狀態的,時刻同步active狀態NameNode的資料。一旦active狀態的NameNode不能工作,通過手工或者自動切換,standby狀態的NameNode就可以轉變為active狀態的,就可以繼續工作了。這就是高可靠。
2.3 JournalNode實現NameNode(Active和Standby)資料的共享
當有兩個NameNode,一個standby一個active,當active有資料變動時,standby也應該及時更新,這樣才可以做到高可靠!否則,資訊不一致還怎麼叫高可靠呢?
兩個NameNode為了資料同步,會通過一組稱作JournalNodes(JNs)的獨立程序進行相互通訊。當active狀態的NameNode的名稱空間有任何修改時,會告知大部分的JournalNodes程序。standby狀態的NameNode有能力讀取JNs中的變更資訊,並且一直監控edit log的變化,把變化應用於自己的名稱空間。standby可以確保在叢集出錯時,名稱空間狀態已經完全同步了
2.4 NameNode之間的故障切換
active的NameNode出現了故障,例如掛機了,是誰去切換standby的NameNode變為active狀態呢?這時,就需要引入ZooKeeper。首先HDFS叢集中的兩個NameNode都在ZooKeeper中註冊,當active狀態的NameNode出故障時,ZooKeeper能檢測到這種情況,它就會自動把standby狀態的NameNode切換為active狀態
主機名 | IP | 安裝軟體 | 執行的程序 |
---|---|---|---|
had01 | 192.168.0.141 | jdk,hadoop | NameNode,DFSZKFailoverController(zkfc) |
had02 | 192.168.0.142 | jdk,hadoop | NameNode,DFSZKFailoverController(zkfc) |
had03 | 192.168.0.143 | jdk,hadoop | ResourceManager |
had04 | 192.168.0.144 | jdk,hadoop | ResourceManager |
had05 | 192.168.0.145 | jdk,hadoop,zookeeper | DataNode,NodeManager、JournalNode、QuorumPeerMain |
had06 | 192.168.0.146 | jdk、hadoop、zookeeper | DataNode、NodeManager、JournalNode、QuorumPeerMain |
had07 | 192.168.0.147 | jdk、hadoop、zookeeper | DataNode、NodeManager、JournalNode、QuorumPeerMain |
3.3 安裝配置zooKeeper叢集(在had05上)
3.3.1 解壓zookeeper的jar
tar -zxvf zookeeper-3.4.5.tar.gz -C ~/app
安裝在使用者主目錄下的app資料夾內
3.3.2 修改配置
cd /weekend/zookeeper-3.4.5/conf/
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
修改:dataDir=/home/hadoop/app/zookeeper-3.4.5/tmp
在最後新增:
server.1=had05:2888:3888
server.2=had06:2888:3888
server.3=had07:2888:3888
儲存退出
然後建立一個tmp資料夾
mkdir /home/hadoop/app/zookeeper-3.4.5/tmp
再建立一個空檔案
touch /home/hadoop/app/zookeeper-3.4.5/tmp/myid
最後向該檔案寫入ID
echo 1 > /home/hadoop/app/zookeeper-3.4.5/tmp/myid
server.x意義:
zooKeeper工作原理:http://www.cnblogs.com/kunpengit/p/4045334.html
zoo.cfg配置檔案:
3.3.3 將配置好的zookeeper拷貝到其它節點
首先分別在had06、had07使用者目錄下建立一個app目錄:mkdir app
scp -r app/zookeeper-3.4.5/ had06:app/
scp -r app/zookeeper-3.4.5/ had07:app/
注意:修改had06、had07對應app/zookeeper-3.4.5/tmp/myid內容
had06:echo 2 > app/zookeeper-3.4.5/tmp/myid
had07:echo 3 > app/zookeeper-3.4.5/tmp/myid
4.安裝配置hadoop叢集
4.1 解壓
tar -zxvf hadoop-2.4.1.tar.gz -C ~/app
4.2 配置HDFS
#將hadoop新增到環境變數中
vi /etc/profile
export JAVA_HOME=/home/hadoop/app/jdk1.7.0_79
export HADOOP_HOME=/home/hadoop/hadoop-2.4.1
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin
進入hadoop的配置資料夾
cd /home/hadoop/app/hadoop-2.4.1/etc/hadoop
4.2.1 修改hadoop-env.sh
export JAVA_HOME=/home/hadoop/app/jdk1.7.0_79
4.2.2 修改core-site.xml
<configuration>
<!-- 指定hdfs的nameservice為ns1 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://ns1</value>
</property>
<!-- 指定hadoop臨時目錄 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/app/hadoop-2.4.1/tmp</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>had05:2181,had06:2181,had07:2181</value>
</property>
</configuration>
4.2.3 修改hdfs-site.xml
<configuration>
<!--指定hdfs的nameservice為ns1,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<!-- ns1下面有兩個NameNode,分別是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通訊地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>had01:9000</value>
</property>
<!-- nn1的http通訊地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>had01:50070</value>
</property>
<!-- nn2的RPC通訊地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>had02:9000</value>
</property>
<!-- nn2的http通訊地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>had02:50070</value>
</property>
<!-- 指定NameNode的元資料在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://had05:8485;had06:8485;had07:8485/ns1</value>
</property>
<!-- 指定JournalNode在本地磁碟存放資料的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/home/hadoop/app/hadoop-2.4.1/journaldata</value>
</property>
<!-- 開啟NameNode失敗自動切換 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置失敗自動切換實現方式 -->
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔離機制方法,多個機制用換行分割,即每個機制暫用一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<!-- 使用sshfence隔離機制時需要ssh免登陸 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔離機制超時時間 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
</configuration>
4.2.4 修改mapred-site.xml
<configuration>
<!-- 指定mr框架為yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
4.2.5 修改yarn-site.xml
<configuration>
<!-- 開啟RM高可用 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 指定RM的cluster id -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yrc</value>
</property>
<!-- 指定RM的名字 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分別指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>had03</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>had04</value>
</property>
<!-- 指定zk叢集地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>had05:2181,had06:2181,had07:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
4.2.6 修改slaves檔案
slaves是指定子節點的位置,因為要在had01上啟動HDFS、在had03啟動yarn,所以had01上的slaves檔案指定的是datanode的位置,had03上的slaves檔案指定的是nodemanager的位置
4.2.7 配置SSH無密登入
首先要配置had01到had02、had03、had04、had05、had06、had07的免密碼登陸,在had01上生產一對鑰匙
ssh-keygen -t rsa
將公鑰拷貝到其他節點,包括自己
ssh-coyp-id had01
ssh-coyp-id had02
ssh-coyp-id had03
ssh-coyp-id had04
ssh-coyp-id had05
ssh-coyp-id had06
ssh-coyp-id had07
配置had03到had04、had05、had06、had07的免密碼登陸
在had03上生產一對鑰匙
ssh-keygen -t rsa
將公鑰拷貝到其他節點
ssh-coyp-id had04
ssh-coyp-id had05
ssh-coyp-id had06
ssh-coyp-id had07
注意:兩個namenode之間要配置ssh免密碼登陸,別忘了配置had02到had01的免登陸
在had02上生產一對鑰匙
ssh-keygen -t rsa
ssh-coyp-id -i had01
4.3 將配置好的hadoop拷貝到其它節點
scp -r ~/app/hadoop-2.4.1 had0x:/home/hadoop/app
x代表主機名稱[2,7]
4.4 啟動zookeeper叢集
分別在had05、had06、had07上啟動zk
cd /home/hadoop/app/zookeeper-3.4.5/bin/
./zkServer.sh start
#檢視狀態:一個leader,兩個follower
./zkServer.sh status
4.5啟動journalnode
分別在had05、had06、had07上啟動
cd /home/hadoop/app/hadoop-2.4.1/sbin/
hadoop-daemon.sh start journalnode
執行jps命令檢驗,had05、had06、had07上多了JournalNode程序
4.6 格式化HDFS
在had01上執行命令:
hdfs namenode -format
格式化後會在根據core-site.xml中的hadoop.tmp.dir配置生成個檔案,這裡我配置的是/home/hadoop/app/hadoop-2.4.1/tmp,然後將/home/hadoop/app/hadoop-2.4.1/tmp拷貝到had02的/home/hadoop/app/hadoop-2.4.1
scp -r tmp/ had02:/home/hadoop/app/hadoop-2.4.1/
也可以這樣,建議
hdfs namenode -bootstrapStandby
4.7 格式化ZKFC
在had01上執行
hdfs zkfc -formatZK
4.8 啟動HDFS
在had01上執行
start-dfs.sh
4.9 啟動YARN
是在had03上執行start-yarn.sh,把namenode和resourcemanager分開是因為效能問題,因為他們都要佔用大量資源,所以把他們分開了,他們分開了就要分別在不同的機器上啟動
start-yarn.sh
5.驗證
5.1驗證HDFS HA
首先向hdfs上傳一個檔案
hadoop fs -put test1.txt test2.txt /input
hadoop fs -ls /input
然後再kill掉active的NameNode
kill -9 <pid of NN>
通過瀏覽器訪問:http://192.168.0.142:50070
NameNode ‘had02:9000’ (active)
這個時候had02上的NameNode變成了active
在執行命令:
hadoop fs -ls /input
剛才上傳的檔案依然存在!!!
手動啟動那個掛掉的NameNode
hadoop-daemon.sh start namenode
通過瀏覽器訪問:http://192.168.0.141:50070
NameNode ‘had01:9000’ (standby)
5.2 驗證YARN
執行一下hadoop提供的demo中的WordCount程式:
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.4.1.jar wordcount /input /out
結果:
PS:
如果只有3臺主機,則可以按照下面規劃部署
主機名 | 安裝軟體 | 執行的程序 |
---|---|---|
had01 | jdk,hadoop,zookeeper | journalnode namenode zkfc resourcemanager datanode |
had02 | jdk,hadoop,zookeeper | journalnode namenode zkfc resourcemanager datanode |
had03 | jdk,hadoop,zookeeper | journalnode datanode |
在叢集搭建過程中出現的BUG集合
1.
ssh-copy-id :command not found
由於安裝的是mini版,所以出現這種問題。解決方案:
yum -y install openssh-clients
2.
查詢一下zookeeper叢集是否已經啟動成功。
在zookeeper目錄bin下
./zkServer.sh status
若是沒有啟動,則手動啟動它,
./zkServer.sh start
3.還有一個問題需要注意的是,主機名不要帶下劃線 “_”