1. 程式人生 > >Hadoop的HA機制(Zookeeper叢集+Hadoop叢集)配置記錄

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.還有一個問題需要注意的是,主機名不要帶下劃線 “_”