1. 程式人生 > >hadoop的HA

hadoop的HA

1. 為什麼要搭建HA?

  在hadoop2.x之前,在HDFS 叢集中NameNode 存在單點故障 (SPOF:A Single Point of Failure)。對於只有一個 NameNode 的叢集,如果 NameNode 機器出現故障(比如宕機或是軟體、硬體升級),那麼整個叢集將無法使用,必須等到 NameNode 重新啟動,之後才能對外提供服務,這個方式在生成環境中是絕對不允許出現的。
  HDFS 的 HA:通過配置 Active/Standby 兩個 NameNodes 實現在叢集中對 NameNode 的熱備來解決上述問題。如果出現故障,如機器崩潰或機器需要升級維護,這時可通過此種方式將 NameNode 很快的切換到另外一臺機器。

2. HA的工作原理?

hadoop的HA
解釋(資料一致以及持久化問題):

  • 當hdfs客戶端連線namenode時,namenode啟動時,會向JN叢集提交edtis log(操作記錄日誌)。
  • 此時在JN叢集中,當有一半的叢集服務成功的接收到了訊息,然後返回給namenode,這就表示edits log上傳成功。
  • 此時NameNode(standBy),需要從JN叢集取回元資料資訊,然後整合新的fsimage,然後推送回NameNode(active)
  • 在NameNode(standBy)向JN索要資料的時候,首先在JN中會檢視是否有宕機的機器,採用過半機制(當叢集中有部分伺服器宕機時,此時叢集會將大部分可以使用的機器作為主,其他的機器全部停止服務),去向備機(standBy)提供對外的資料傳輸。
  • 在解決block 塊資訊時,此時datanode會向兩臺namenode都發送block 塊資訊。
    解釋(解決主備切換問題):
  • 此時需要使用到另外一個叢集zookeeper,zookeeper叢集是一個高可用的叢集,它的實現機制是,首先是一個伺服器提供對外的服務,其他的機器是備機,當主機壞了的時候,此時zookeeper叢集中採取投票機制(邏輯時鐘,ID號,以及資料的更新程度),選出新的主。
  • 此時ZKFC務控制執行緒一直手抓住了zookeeper叢集,另一隻手抓住了NameNode。
    • 抓住NameNode(active)的服務控制,監控NameNode(active)的狀態,實時的向zookeeper叢集彙報。
    • 住NameNode(standBy)的服務控制,接收zookeeper叢集傳送的資訊,如果傳送過來的資訊,表示主NameNode已停止服務,立刻呼叫服務控制中的回撥函式,讓NameNode(standBy)變成主機繼續提供服務。
  •  以上的作用是一個和keeplive相同的作用,使用zookeeper不同之處在於,如果服務控制處出現程序的異常退出時,此時通過zookeeper叢集會將備機改為active狀態,此時主機可能還是active,就造成了兩臺active的NameNode。在zookeeper中是這樣解決的:當有一個服務控制程序異常退出後,他會有一隻無形的手去連線另外一臺NameNode,並且在可控的範圍內,將其變成主(active),而將自己無法控制的那臺NameNode,變成備機。

    3. HA的叢集搭建?

    搭建叢集前的準備:http://blog.51cto.com/14048416/2341450
    zookeeper叢集的搭建:http://blog.51cto.com/14048416/2336178

    1)叢集的規劃

    hadoop的HA

    2)具體安裝步驟:

    1)上傳安裝包 hadoop-2.6.5-centos-6.7.tar.gz

    2)解壓到對應的安裝目錄

    [[email protected] ~]$tar -zxvf hadoop-2.6.5-centos-6.7.tar.gz -C /home/hadoop/apps/

    3)修改配置檔案

    hadoo-env.sh:
    加入:export JAVA_HOME= /usr/local/jdk1.8.0_73

core-site.xml

<configuration>
<!-- 指定 hdfs 的 nameservice 為 myha01 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://myha01/</value>
</property>
<!-- 指定 hadoop 工作目錄 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/data/hadoopdata/</value>
</property>
<!-- 指定 zookeeper 叢集訪問地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
</property>
</configuration>

hdfs-site.xml

<configuration>
<!-- 指定副本數 -->
<property>
 <name>dfs.replication</name>
 <value>3</value>
</property>
<!--指定 hdfs 的 nameservice 為 myha01,需要和 core-site.xml 中保持一致-->
<property>
 <name>dfs.nameservices</name>
 <value>myha01</value>
</property>
<!-- myha01 下面有兩個 NameNode,分別是 nn1,nn2 -->
<property>
 <name>dfs.ha.namenodes.myha01</name>
 <value>nn1,nn2</value>
</property>
<!-- nn1 的 RPC 通訊地址 -->
<property>
 <name>dfs.namenode.rpc-address.myha01.nn1</name>
 <value>hadoop01:9000</value>
</property>
<!-- nn1 的 http 通訊地址 -->
<property>
 <name>dfs.namenode.http-address.myha01.nn1</name>
 <value>hadoop01:50070</value>
</property>
<!-- nn2 的 RPC 通訊地址 -->
<property>
 <name>dfs.namenode.rpc-address.myha01.nn2</name>
 <value>hadoop02:9000</value>
</property>
<!-- nn2 的 http 通訊地址 -->
<property>
 <name>dfs.namenode.http-address.myha01.nn2</name>
 <value>hadoop02:50070</value>
</property>
<!-- 指定 NameNode 的 edits 元資料在 JournalNode 上的存放位置 -->
<property>
 <name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop01:8485;hadoop02:8485;hadoop03:8485/myha01</value>
</property>
<!-- 指定 JournalNode 在本地磁碟存放資料的位置 -->
<property>
 <name>dfs.journalnode.edits.dir</name>
 <value>/home/hadoop/data/journaldata</value>
</property>
<!-- 開啟 NameNode 失敗自動切換 -->
<property>
 <name>dfs.ha.automatic-failover.enabled</name>
 <value>true</value>
</property>
<!-- 配置失敗自動切換實現方式 -->
<!-- 此處配置在安裝的時候切記檢查不要換行-->
<property>
 <name>dfs.client.failover.proxy.provider.myha01</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverPr
oxyProvider</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>

mapred-site.xml

<configuration>
<!-- 指定 mr 框架為 yarn 方式 -->
<property>
 <name>mapreduce.framework.name</name>
 <value>yarn</value>
</property>
<!-- 設定 mapreduce 的歷史伺服器地址和埠號 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop02:10020</value>
</property>
<!-- mapreduce 歷史伺服器的 web 訪問地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop02:19888</value>
</property>
</configuration>

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>hadoop01</value>
</property>
<property>
 <name>yarn.resourcemanager.hostname.rm2</name>
 <value>hadoop02</value>
</property>
<!-- 指定 zk 叢集地址 -->
<property>
 <name>yarn.resourcemanager.zk-address</name>
 <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
</property>
<!-- 要執行 MapReduce 程式必須配置的附屬服務 -->
<property>
 <name>yarn.nodemanager.aux-services</name>
 <value>mapreduce_shuffle</value>
</property>
<!-- 開啟 YARN 叢集的日誌聚合功能 -->
<property>
 <name>yarn.log-aggregation-enable</name>
 <value>true</value>
</property>
<!-- YARN 叢集的聚合日誌最長保留時長 -->
<property>
 <name>yarn.log-aggregation.retain-seconds</name>
 <value>86400</value>
</property>
<!-- 啟用自動恢復 -->
<property>
 <name>yarn.resourcemanager.recovery.enabled</name>
 <value>true</value>
</property>
<!-- 制定 resourcemanager 的狀態資訊儲存在 zookeeper 叢集上-->
<property>
 <name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
</configuration>

slaves

hadoop01
hadoop02
hadoop03

4)分發安裝包到其他機器

[[email protected] apps]$scp -r hadoop-2.6.5 [email protected]:$PWD
[[email protected] apps]$scp -r hadoop-2.6.5 [email protected]:$PWD

5)分別配置環境變數

[[email protected] apps]$ vi ~/.bashrc
新增兩行:

export HADOOP_HOME=/home/hadoop/apps/hadoop-2.6.5
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

[[email protected] apps]$ source ~/.bashrc

6)叢集初始化操作

先啟動 zookeeper 叢集
啟動:zkServer.sh start
檢查啟動是否正常:zkServer.sh status
啟動 journalnode 程序
[[email protected] ~]$ hadoop-daemon.sh start journalnode
[[email protected] ~]$ hadoop-daemon.sh start journalnode
[[email protected] ~]$ hadoop-daemon.sh start journalnode
然後用 jps 命令檢視是否各個 datanode 節點上都啟動了 journalnode 程序
在第一個 namenode 上執行格式化操作
[[email protected] ~]$ hadoop namenode -format
hadoop的HA
然後會在 core-site.xml 中配置的臨時目錄中生成一些叢集的資訊把他拷貝的第二個 namenode 的相同目錄下
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/data/hadoopdata/</value>
兩個 namenode 節點該目錄中的資料結構是一致的
[[email protected] ~]$ scp -r ~/data/hadoopdata/ hadoop03:~/data
或者在另一個namenode節點上使用:hadoop namenode -bootstrapStandby
格式化 ZKFC(在一臺叢集上格式化即可):
[[email protected] ~]$ hdfs zkfc -formatZK
啟動 HDFS
[[email protected] ~]$ start-dfs.sh
啟動 YARN
[[email protected] ~]$ start-yarn.sh
若備用節點的 resourcemanager 沒有啟動起來,則手動啟動起來:
[[email protected] ~]$ yarn-daemon.sh start resourcemanager

7)補充:

檢視各主節點的狀態
HDFS:
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2

YARN:
yarn rmadmin -getServiceState rm1
yarn rmadmin -getServiceState rm2

4. HA的叢集搭建後測試

1.手動殺死active的namenode,看看叢集的狀況
2.手動殺死active的resourcemanager,看看叢集的狀況
3.在上傳檔案時,殺死namenode,檢視叢集狀況
4.在執行任務時,殺死resourcemanager,檢視叢集狀態