一.概述

      在hadoop1時代,只有一個NameNode。如果該NameNode資料丟失或者不能工作,那麼整個叢集就不能恢復了。這是hadoop1中的單點問題,也是hadoop1不可靠的表現。

     在典型的 HA 叢集中,通常有兩臺不同的機器充當 NN。在任何時間,只有一臺機器處於Active 狀態;另一臺機器是處於 Standby 狀態。Active NN 負責叢集中所有客戶端的操作;而 Standby NN 主要用於備用,它主要維持足夠的狀態,如果必要,可以提供快速的故障恢復。為了讓 Standby NN 的狀態和 Active NN 保持同步,即元資料保持一致,它們都將會和JournalNodes 守護程序通訊。當 Active NN 執行任何有關名稱空間的修改,它需要持久化到一半以上的 JournalNodes 上(通過 edits log 持久化儲存),而 Standby NN 負責觀察 edits log的變化,它能夠讀取從 JNS 中讀取 edits 資訊,並更新其內部的名稱空間。一旦 Active NN出現故障,Standby NN 將會保證從 JNS 中讀出了全部的 Edits,然後切換成 Active 狀態。Standby NN 讀取全部的 edits 可確保發生故障轉移之前,是和 Active NN 擁有完全同步的名稱空間狀態。為了提供快速的故障恢復,Standby NN 也需要儲存叢集中各個檔案塊的儲存位置。為了實現這個,叢集中所有的 Database 將配置好 Active NN 和 Standby NN 的位置,並向它們傳送塊檔案所在的位置及心跳,如下圖所示:

       在任何時候,叢集中只有一個 NN 處於 Active 狀態是極其重要的。否則,在兩個 Active NN的狀態下 NameSpace 狀態將會出現分歧,這將會導致資料的丟失及其它不正確的結果。為了保證這種情況不會發生,在任何時間,JNs 只允許一個 NN 充當 writer。在故障恢復期間,將要變成 Active 狀態的 NN 將取得 writer 的角色,並阻止另外一個 NN 繼續處於 Active狀態。同時我們使用zookeeper。首先HDFS叢集中的兩個NameNode都在ZooKeeper中註冊,當active狀態的NameNode出故障時,ZooKeeper能檢測到這種情況,它就會自動把standby狀態的NameNode切換為active狀態。。
為了部署 HA 叢集,你需要準備以下事項:
(1)、NameNode machines:執行 Active NN 和 Standby NN 的機器需要相同的硬體配置;
(2)、JournalNode machines:也就是執行 JN 的機器。JN 守護程序相對來說比較輕量,所以這些守護程序可以和其他守護執行緒(比如 NN,YARN ResourceManager)執行在同一臺機器上。在一個叢集中,最少要執行 3 個 JN 守護程序,這將使得系統有一定的容錯能力。當然,你也可以執行 3 個以上的 JN,但是為了增加系統的容錯能力,你應該執行奇數個 JN(3、5、7 等),當執行 N 個 JN,系統將最多容忍(N-1)/2 個 JN 崩潰。在 HA 叢集中,Standby NN 也執行namespace 狀態的 checkpoints,所以不必要執行Secondary NN、CheckpointNode 和 BackupNode;事實上,執行這些守護程序是錯誤的。

二.Hadoop(HA)叢集的搭建

系統環境:RHEL6.5 selinux and iptables is disabled
               Hadoop 、jdk、zookeeper 程式使用 nfs 共享同步配置檔案
軟體版本:hadoop-2.7.3.tar.gz zookeeper-3.4.9.tar.gz jdk-7u79-linux-x64.tar.gz
               hbase-1.2.4-bin.tar.gz
主機列表:

IP 主機名 角色
172.25.66.1

server1.example.com

NameNode
DFSZKFailoverController
ResourceManager
172.25.66.5 server5.example.com NameNode
DFSZKFailoverController
ResourceManager
172.25.66.2 server2.example.com JournalNode
QuorumPeerMain
DataNode
NodeManager
172.25.66.3 server3.example.com JournalNode
QuorumPeerMain
DataNode
NodeManager
172.25.66.4 server4.example.com JournalNode
QuorumPeerMain
DataNode
NodeManager

該實驗中相關主機的配置可參考前兩篇部落格

server5:

[[email protected] ~]# yum install nfs-utils
[[email protected] ~]# useradd -u 800 hadoop
[[email protected] ~]# passwd hadoop
Changing password for user hadoop.
New password: 
BAD PASSWORD: it is based on a dictionary word
BAD PASSWORD: is too simple
Retype new password: 
passwd: all authentication tokens updated successfully.
[[email protected] ~]# /etc/init.d/rpcbind start
Starting rpcbind:                                          [  OK  ]
[[email protected] ~]# /etc/init.d/nfs start
Starting NFS services:                                     [  OK  ]
Starting NFS mountd:                                       [  OK  ]
Starting NFS daemon:                                       [  OK  ]
Starting RPC idmapd:                                       [  OK  ]
[[email protected] ~]# mount 172.25.66.1:/home/hadoop/ /home/hadoop
[[email protected] ~]# su - hadoop
[[email protected] ~]$ ls
hadoop        hadoop-2.7.3.tar.gz  jdk1.7.0_79
hadoop-2.7.3  java                 jdk-7u79-linux-x64.tar.gz

保證server1能不需要密碼登陸server5

[[email protected] ~]$ tar zxf zookeeper-3.4.9.tar.gz 
[[email protected] ~]$ ls
hadoop               java                       zookeeper-3.4.9
hadoop-2.7.3         jdk1.7.0_79                zookeeper-3.4.9.tar.gz
hadoop-2.7.3.tar.gz  jdk-7u79-linux-x64.tar.gz
[[email protected] ~]$ cd zookeeper-3.4.9
[[email protected] zookeeper-3.4.9]$ ls
build.xml  dist-maven  ivy.xml  LICENSE.txt  src
conf       docs        lib      recipes      zookeeper-3.4.9.jar
[[email protected] zookeeper-3.4.9]$ cd conf
[[email protected] conf]$ ls
configuration.xsl  log4j.properties  zoo_sample.cfg
[[email protected] conf]$ cp zoo_sample.cfg zoo.cfg
[[email protected] conf]$ vim zoo.cfg  ##編輯zookeeper配置檔案

各節點配置檔案相同,並且需要在/tmp/zookeeper 目錄中建立 myid 檔案,寫入一個唯一的數字,取值範圍在 1-255。比如:172.25.0.2 節點的 myid 檔案寫入數字“1”,此數字與配置檔案中的定義保持一致,(server.1=172.25.66.2:2888:3888)其它節點依次類推

在各節點啟動服務,並檢視狀態

剛開始時出現了報錯:

服務能夠啟動,但檢視狀態時顯示not running

檢視zookeeper.out日誌檔案,看有沒有Error報錯。通過報錯,說明2181埠被佔用,通過netstat -nltp | grep 2181檢查是否已被佔用,如果有則把對應的程序kill掉(kill 程序的pid),然後再啟動zookeeper,問題解決

配置hadoop

server1:

1.編輯core-site.xml檔案

<configuration>
<!-- 指定 hdfs 的 namenode 為 masters (名稱可自定義)-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://masters</value>
</property>
<!-- 指定 zookeeper 叢集主機地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>172.25.66.2:2181,172.25.66.3:2181,172.25.66.4:2181</value>
</property>
</configuration>

2.編輯hdfs-site.xml

<configuration>
<!-- 指定 hdfs 的 nameservices 為 masters,和 core-site.xml 檔案中的設定保持一致 -->
<property>
     <name>dfs.nameservices</name>
     <value>masters</value>
</property>
<!-- masters 下面有兩個 namenode 節點,分別是 h1 和 h2 (名稱可自定義)-->
<property>
      <name>dfs.ha.namenodes.masters</name>
      <value>h1,h2</value>
</property>
<!-- 指定 h1 節點的 rpc 通訊地址 -->
<property>
    <name>dfs.namenode.rpc-address.masters.h1</name>
    <value>172.25.66.1:9000</value>
</property>
<!-- 指定 h1 節點的 http 通訊地址 -->
<property>
    <name>dfs.namenode.http-address.masters.h1</name>
    <value>172.25.66.1:50070</value>
</property>
<!-- 指定 h2 節點的 rpc 通訊地址 -->
<property>
     <name>dfs.namenode.rpc-address.masters.h2</name>
     <value>172.25.66.5:9000</value>
</property>
<!-- 指定 h2 節點的 http 通訊地址 -->
<property>
     <name>dfs.namenode.http-address.masters.h2</name>
     <value>172.25.66.5:50070</value>
</property>
<!-- 指定 NameNode 元資料在 JournalNode 上的存放位置 -->
<property>
     <name>dfs.namenode.shared.edits.dir</name>
     <value>qjournal://172.25.66.2:8485;172.25.66.3:8485;172.25.66.4:8485/masters</value>
</property>
<!-- 指定 JournalNode 在本地磁碟存放資料的位置 -->
<property>
     <name>dfs.journalnode.edits.dir</name>
     <value>/tmp/journaldata</value>
</property>
<!-- 開啟 NameNode 失敗自動切換 -->
<property>
     <name>dfs.ha.automatic-failover.enabled</name>
     <value>true</value>
</property>
<!-- 配置失敗自動切換實現方式 -->
<property>
    <name>dfs.client.failover.proxy.provider.masters</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvid
er</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>

3.編輯slaves檔案

4. 啟動 hdfs 叢集(按順序啟動)
1)在三個 DN 上依次啟動 zookeeper 叢集

2)在三個 DN 上依次啟動 journalnode(第一次啟動 hdfs 必須先啟動 journalnode)

3)格式化 HDFS 叢集

Namenode 資料預設存放在/tmp,需要把資料拷貝到 h2

[[email protected] hadoop]$ bin/hdfs namenode -format
[[email protected] hadoop]$ scp -r /tmp/hadoop-hadoop/ 172.25.66.5:/tmp

4)格式化 zookeeper (只需在 h1 上執行即可)

[[email protected] hadoop]$ bin/hdfs zkfc -formatZK


5)啟動 hdfs 叢集(只需在 h1 上執行即可)

6) 檢視各節點狀態

檢視各節點狀態中出現的錯誤:

1.發現server3的nodedata節點啟動失敗,檢視日誌

原因:每次namenode format會重新建立一個namenodeId,而data目錄包含了上次format時的id,namenode format清空了namenode下的資料,但是沒有清空datanode下的資料,導致啟動時失敗,所要做的就是每次fotmat前,清空data下的所有目錄.

解決辦法:停掉叢集,刪除問題節點的data目錄下的所有內容。即hdfs-site.xml檔案中配置的dfs.data.dir目錄。重新格式化namenode。

[[email protected] hadoop]$ cd /tmp/
[[email protected] tmp]$ ls
hadoop-hadoop
hsperfdata_hadoop
Jetty_0_0_0_0_8480_journal____.8g4awa
Jetty_localhost_36989_datanode____.h3ojj6
Jetty_localhost_47197_datanode____btc3o3
Jetty_localhost_48545_datanode____cjqes9
Jetty_localhost_51373_datanode____ssfp22
Jetty_localhost_54872_datanode____.936znp
Jetty_localhost_58314_datanode____f00o6y
Jetty_localhost_60332_datanode____qvofjz
journaldata
zookeeper
[[email protected] tmp]$ rm -rf Jetty_*
[[email protected] tmp]$ ls
hadoop-hadoop  hsperfdata_hadoop  journaldata  zookeeper

2.兩個namenode啟動不起來

檢視日誌: cat hadoop-hadoop-namenode-server5.log

原因:namenode元資料被破壞,需要修復
解決:恢復一下namenode

cd 
cd hadoop 
./bin/hadoop namenode -recover

在瀏覽器中進行測試:

7) 測試故障自動切換

因為server5是處於active的namenode節點,所以kill掉server5的NameNode程序

刷新發現active跳到server1上:實現高可用

重新開啟server5的namenode:

重新整理後server5變為可standby狀態

到此 hdfs 的高可用完成

三、yarn 的高可用

server1:

1) 編輯 mapred-site.xml 檔案

指定yarn為mapreduce的框架

2)編輯 yarn-site.xml 檔案

<configuration>
<!-- 配置可以在 nodemanager 上執行 mapreduce 程式 -->
<property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
</property>
<!-- 啟用 RM 高可用 -->
<property>
   <name>yarn.resourcemanager.ha.enabled</name>
   <value>true</value>
</property>
<!-- 指定 RM 的叢集 id -->
<property>
    <name>yarn.resourcemanager.cluster-id</name>
    <value>RM_CLUSTER</value>
</property>
<!-- 定義 RM 的節點-->
<property>
    <name>yarn.resourcemanager.ha.rm-ids</name>
    <value>rm1,rm2</value>
</property>
<!-- 指定 RM1 的地址 -->
<property>
    <name>yarn.resourcemanager.hostname.rm1</name>
    <value>172.25.66.1</value>
</property>
<!-- 指定 RM2 的地址 -->
<property>
    <name>yarn.resourcemanager.hostname.rm2</name>
    <value>172.25.66.5</value>
</property>
<!-- 啟用 RM 自動恢復 -->
<property>
    <name>yarn.resourcemanager.recovery.enabled</name>
    <value>true</value>
</property>
<!-- 配置 RM 狀態資訊儲存方式,有 MemStore 和 ZKStore-->
<property>
   <name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</
value>
</property>
<!-- 配置為 zookeeper 儲存時,指定 zookeeper 叢集的地址 -->
<property>
    <name>yarn.resourcemanager.zk-address</name>
    <value>172.25.66.2:2181,172.25.66.3:2181,172.25.66.4:2181</value>
</property>
</configuration>

3)啟動 yarn 服務

RM2 上需要手動啟動

4) 測試 yarn 故障切換

server5的RM web服務被重定向到活躍的RM。

kill 掉server1的RS程序

server5的RS狀態變為了active

四、部署hbase

HBase是一個分散式的、面向列的開源資料庫,該技術來源於 Fay Chang 所撰寫的Google論文“Bigtable:一個結構化資料的分散式儲存系統”。 就像Bigtable利用了Google檔案系統(File System)所提供的分散式資料儲存一樣,HBase在Hadoop之上提供了類似於Bigtable的能力。HBase是Apache的Hadoop 專案的子專案。HBase不同於一般的關係資料庫,它是一個適合於非結構化資料儲存的資料庫。另一個不同的是HBase基於列的而不是基於行的模式。

[[email protected] ~]$ tar zxf hbase-1.2.4-bin.tar.gz 
[[email protected] ~]$ ls
hadoop               hbase-1.2.4-bin.tar.gz     zookeeper-3.4.9
hadoop-2.7.3         java                       zookeeper-3.4.9.tar.gz
hadoop-2.7.3.tar.gz  jdk1.7.0_79
hbase-1.2.4          jdk-7u79-linux-x64.tar.gz
[[email protected] ~]$ cd hbase-1.2.4
[[email protected] hbase-1.2.4]$ cd
[[email protected] ~]$ cd hbase-1.2.4/conf/
[[email protected] conf]$ ls
hadoop-metrics2-hbase.properties  hbase-policy.xml  regionservers
hbase-env.cmd                     hbase-site.xml
hbase-env.sh                      log4j.properties
[[email protected] conf]$ vim hbase-env.sh 

export JAVA_HOME=/home/hadoop/java   #指定 jdk
export HBASE_MANAGES_ZK=false    #預設值是 true,hbase 在啟動時自動開啟 zookeeper,如需自己維護 zookeeper 叢集需設定為 false
export HADOOP_HOME=/home/hadoop/hadoop #指定 hadoop 目錄,否則 hbase無法識別 hdfs 叢集配置。

2)編輯hbase-site.xml

<configuration>
  指定 region server 的共享目錄,用來持久化 HBase。這裡指定的 HDFS 地址
是要跟 core-site.xml 裡面的 fs.defaultFS 的 HDFS 的 IP 地址或者域名、埠必須一致
       <property>
       <name>hbase.rootdir</name>
       <value>hdfs://masters/hbase</value>
       </property>
  啟用 hbase 分散式模式
       <property>
       <name>hbase.cluster.distributed</name>
       <value>true</value>
       </property>
       <property>
  Zookeeper 叢集的地址列表,用逗號分割。預設是 localhost,是給偽分散式用
的。要修改才能在完全分散式的情況下使用
       <name>hbase.zookeeper.quorum</name>
       <value>172.25.66.2,172.25.66.3,172.25.66.4</value>
       </property>
  指定資料拷貝 2 份,hdfs 預設是 3 份
       <property>
       <name>dfs.replication</name>
       <value>2</value>
       </property>
  指定 hbase 的 master
       <property><name>hbase.master</name>
       <value>h1</value>
       </property>
</configuration>

3)編輯regionservers

4)啟動 hbase

5)備節點執行:

HBase Master 預設埠時 16000,還有個 web 介面預設在 Master 的 16010 埠上,HBase RegionServers 會預設繫結 16020 埠,在埠 16030 上有一個展示資訊的介面。

6) 測試

[[email protected] hbase-1.2.4]$ bin/hbase shell

繼續通過HBase Shell,HBase的命令列工具檢視,發現數據並沒有丟失