hadoop HA原理概述
爲什麼會有 hadoop HA 機制呢?
- HA:High Available,高可用
在Hadoop 2.0之前,在HDFS 集羣中NameNode 存在單點故障 (SPOF:A Single Point of Failure)。對於只有一個 NameNode 的集羣,如果 NameNode 機器出現故障(比如宕機或是軟件、硬件升級),那麼整個集羣將無法使用,直到 NameNode 重新啓動。 - 那如何解決呢?HDFS 的 HA 功能通過配置 Active/Standby 兩個 NameNodes 實現在集羣中對 NameNode 的熱備來解決上述問題。如果出現故障,如機器崩潰或機器需要升級維護,這時可通過此種方式將 NameNode 很快的切換到另外一臺機器。
- 在一個典型的 HDFS(HA) 集羣中,使用兩臺單獨的機器配置爲 NameNodes 。在任何時間點,確保 NameNodes 中只有一個處於 Active 狀態,其他的處在 Standby 狀態。其中ActiveNameNode 負責集羣中的所有客戶端操作,StandbyNameNode 僅僅充當備機,保證一旦 ActiveNameNode 出現問題能夠快速切換。
- 爲了能夠實時同步 Active 和 Standby 兩個 NameNode 的元數據信息(實際上 editlog),需提供一個共享存儲系統,可以是 NFS、QJM(Quorum Journal Manager)或者 Zookeeper,ActiveNamenode 將數據寫入共享存儲系統,而 Standby 監聽該系統,一旦發現有新數據寫入,則讀取這些數據,並加載到自己內存中,以保證自己內存狀態與 Active NameNode 保持基本一致,如此這般,在緊急情況下 standby 便可快速切爲 active namenode。爲了實現快速切換,Standby 節點獲取集羣的最新文件塊信息也是很有必要的。爲了實現這一目標,DataNode 需要配置 NameNodes 的位置,並同時給他們發送文件塊信息以及心跳檢測。
SecondaryNameNode 和 Standby Namenode 的區別?
在1.x版本中,SecondaryNameNode將fsimage跟edits進行合併,生成新的fsimage文件用http post傳回NameNode節點。SecondaryNameNode不能做NameNode的備份。
在hadoop 2.x版本中才引入StandbyNameNode,從journalNode上拷貝的。StandbyNameNode是可以做namenode的備份。
Hadoop2的高可用並取代SecondaryNamenode
在hadoop2實際生產環境中,爲什麼還需要SecondeNamenode
secondary namenode和namenode的區別
集羣規劃
描述:hadoop HA 集羣的搭建依賴於 zookeeper,所以選取三臺當做 zookeeper 集羣我總共準備了四臺主機,分別是 hadoop02,hadoop03,hadoop04,hadoop05其中 hadoop02 和 hadoop03 做 namenode 的主備切換,hadoop04 和 hadoop05 做resourcemanager 的主備切換
集羣服務器準備
1、 修改主機名
2、 修改 IP 地址
3、 添加主機名和 IP 映射
4、 添加普通用戶 hadoop 用戶並配置 sudoer 權限
5、 設置系統啓動級別
6、 關閉防火牆/關閉 Selinux
7、 安裝 JDK
兩種準備方式:
1、 每個節點都單獨設置,這樣比較麻煩。線上環境可以編寫腳本實現
2、 虛擬機環境可是在做完以上 7 步之後,就進行克隆
3、 然後接着再給你的集羣配置 SSH 免密登陸和搭建時間同步服務
8、 配置 SSH 免密登錄
9、 同步服務器時間
集羣安裝
1、安裝 Zookeeper 集羣(略)
2、 安裝 hadoop 集羣
修改配置文件:
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/data1/hadoopdata/</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181,hadoop04:2181,hadoop05:2181</value>
</property>
<!-- hadoop鏈接zookeeper的超時時長設置 -->
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>1000</value>
<description>ms</description>
</property>
</configuration>
hdfs-site.xml:
<configuration>
<!-- 指定副本數-->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<!-- 配置namenode和datanode的工作目錄-數據存儲目錄-->
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/data1/hadoopdata/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/data1/hadoopdata/dfs/data</value>
</property>
<!-- 啓用webhdfs-->
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<!--指定hdfs的nameservice爲myha01,需要和core-site.xml中的保持一致
dfs.ha.namenodes.[nameservice id]爲在nameservice中的每一個NameNode設置唯一標示符。
配置一個逗號分隔的NameNode ID列表。這將是被DataNode識別爲所有的NameNode。
例如,如果使用"myha01"作爲nameservice ID,並且使用"nn1"和"nn2"作爲NameNodes標示符
-->
<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列表
該url的配置格式:qjournal://host1:port1;host2:port2;host3:port3/journalId
journalId推薦使用nameservice,默認端口號是:8485 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop02:8485;hadoop03:8485;hadoop04:8485/myha01</value>
</property>
<!-- 指定JournalNode在本地磁盤存放數據的位置-->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/home/hadoop/data1/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.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>
<property>
<name>ha.failover-controller.cli-check.rpc-timeout.ms</name>
<value>60000</value>
</property>
</configuration>
mapred-site.xml:
<configuration>
<!--指定mr框架爲yarn方式-->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!--指定mapreduce jobhistory-->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop01:10020</value>
</property>
<!--任務歷史服務器的web地址-->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop01: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>hadoop03</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop04</value>
</property>
<!-- 指定zk集羣地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181,hadoop04:2181,hadoop05:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<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>
hadoop-env.sh: 修改JAVA_HOME
slaves文件:修改映射
注意:配置文件是最容易出錯的地方,建議複製,不建議手寫,容易出錯。格式化namenode之後,如果出錯了,建議刪除臨時文件日誌目錄,每臺機器都要刪除,重新格式化,注意順序步驟。
如果DFSZKFailoverController自動死掉,則有可能是因爲以下配置問題:
錯誤配置,會導致DFSZKFailoverController死掉:
正確寫法,注意sshfence不能換行:
分發安裝包到其他機器
scp -r hadoop-2.7.5 hadoop@hadoop02:$PWD
scp -r hadoop-2.7.5 hadoop@hadoop03:$PWD
scp -r hadoop-2.7.5 hadoop@hadoop04:$PWD
scp -r hadoop-2.7.5 hadoop@hadoop05:$PWD
並分別配置環境變量
vi ~/.bashrc
添加兩行:
export HADOOP_HOME=/home/hadoop/apps/hadoop-2.6.5
export PATH= HADOOP_HOME/bin:$HADOOP_HOME/sbin
保存退出
集羣初始化操作:(注意:嚴格按照以下步驟執行)
1、 先啓動 zookeeper 集羣
啓動:zkServer.sh start
檢查啓動是否正常:zkServer.sh status
2、 分別在每個 zookeeper(也就是規劃的三個 journalnode 節點,不一定跟 zookeeper
節點一樣)節點上啓動 journalnode 進程
[hadoop@hadoop01 ~]$ hadoop-daemon.sh start journalnode
[hadoop@hadoop02 ~]$ hadoop-daemon.sh start journalnode
[hadoop@hadoop03 ~]$ hadoop-daemon.sh start journalnode
[hadoop@hadoop04 ~]$ hadoop-daemon.sh start journalnode
[hadoop@hadoop05 ~]$ hadoop-daemon.sh start journalnode
然後用 jps 命令查看是否各個 datanode 節點上都啓動了 journalnode 進程
如果報錯,根據錯誤提示改進
3、在第一個 namenode 上執行格式化操作
然後會在 core-site.xml 中配置的臨時目錄中生成一些集羣的信息
把他拷貝的第二個 namenode 的相同目錄下
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/data/hadoopdata/</value>
這個目錄下,千萬記住:兩個 namenode 節點該目錄中的數據結構是一致的
[hadoop@hadoop02 ~]$ scp -r ~/data/hadoopdata/ hadoop03:~/data
或者也可以在另一個 namenode 上執行:hadoop namenode -bootstrapStandby
[hadoop@hadoop02 ~]$ hadoop namenode -format
4、格式化 ZKFC
[hadoop@hadoop02 ~]$ hdfs zkfc -formatZK
在第一臺機器上即可
5、啓動 HDFS
[hadoop@hadoop02 ~]$ start-dfs.sh
查看各節點進程是否啓動正常:依次爲 2345 四臺機器的進程
最終效果:
訪問 web 頁面 http://hadoop01:50070
訪問 web 頁面 http://hadoop02:50070
啓動 YARN
[hadoop@hadoop04 ~]$ start-yarn.sh
在主備 resourcemanager 中隨便選擇一臺進行啓動,正常啓動之後,檢查各節點的進程:
若備用節點的 resourcemanager 沒有啓動起來,則手動啓動起來
[hadoop@hadoop04 ~]$ yarn-daemon.sh start resourcemanager
訪問頁面:http://hadoop03:8088
訪問頁面:http://hadoop04:8088 自動跳轉至hadoop03機器
查看各主節點的狀態
HDFS:
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2
YARN:
yarn rmadmin -getServiceState rm1
yarn rmadmin -getServiceState rm2
啓動 mapreduce 任務歷史服務器
[hadoop@hadoop01 ~]$ mr-jobhistory-daemon.sh start historyserver
按照配置文件配置的歷史服務器的 web 訪問地址去訪問:
http://hadoop01:19888
集羣啓動測試
1、幹掉 active namenode, 看看集羣有什麼變化
幹掉active namenode,standby namenode瞬間轉爲active狀態;重新啓動剛纔那臺幹掉的節點後,該節點變爲standby 狀態。
2、在上傳文件的時候幹掉 active namenode, 看看有什麼變化
會報錯,但是可以上傳成功。
3、幹掉 active resourcemanager, 看看集羣有什麼變化
hadoop03上的yarn節點就不能訪問,hadoop05上的yarn節點可以正常訪問。
4、在執行任務的時候幹掉 active resourcemanager,看看集羣
執行wordcount程序,執行的時候,在hadoop03節點上殺死ResourceManager,最終能夠成功執行。