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 的位置,并同时给他们发送文件块信息以及心跳检测。
在典型的HA群集中,两台独立的计算机配置为NameNode。在任何时间点,其中一个NameNode处于活动状态,另一个处于待机状态。
为了使备用节点保持其状态与Active节点同步,两个节点都与一组称为“JournalNodes”(JN)的单独守护进程通信。
机器分配:
NN 需要大内存的机器
DN 需要大硬盘量的机器
JN 无要求 仅仅数据读写
JN集群保证NN和SNN数据的同步,即使没有ZK也能正常运作。但是需要手动切换NN和SNN,即使NN挂掉也需要手动向SNN激活。
配置HA时,主要变动core-site.xml
和hdfs-site.xml
文件。
不使用ZK时,hadoopHA集群搭建如下:
非HA时原core-site.xml:
<configuration>
<property>
<name>fs.defaultFSname>
<value>hdfs://hadoop-master1:9000value>
property>
<property>
<name>hadoop.tmp.dirname>
<value>file:/home/hadoop/datavalue>
<description>Abase for other temporary directories.description>
property>
<property>
<name>net.topology.script.file.namename>
<value>/home/hadoop/hadoop-current/etc/hadoop/RackAware.pyvalue>
property>
configuration>
未做HA时,fs.defaultFS
写到具体的端口。
做HA时,fs.defaultFS
写的是一个引用,该引用的值在hdfs-site
中配置。
如下:
HA的core-site.xml
:
<configuration>
<property>
<name>fs.defaultFSname>
<value>hdfs://hadoop-ns1value>
property>
<property>
<name>hadoop.tmp.dirname>
<value>file:/home/hadoop/datavalue>
<description>Abase for other temporary directories.description>
property>
<property>
<name>net.topology.script.file.namename>
<value>/home/hadoop/hadoop-current/etc/hadoop/RackAware.pyvalue>
property>
configuration>
上边将fs.defaultFS的值改成了一个引用链接,名字自取。其他部分不变。
未做HA时的hdfs-site.xml
:其中nameservices
并没有使用上。
未HA时的hdfs-site.xml
:
<configuration>
<property>
<name>dfs.nameservicesname>
<value>hadoop-clustervalue>
property>
<property>
<name>dfs.replicationname>
<value>3value>
property>
<property>
<name>dfs.namenode.name.dirname>
<value>file:///home/hadoop/data/dfs/nnvalue>
property>
<property>
<name>dfs.datanode.data.dirname>
<value>file:///home/hadoop/data/dfs/dnvalue>
property>
<property>
<name>dfs.namenode.secondary.http-addressname>
<value>hadoop-master1:9001value>
property>
configuration>
HA时的hdfs-site.xml
:其中有三点配置要注意:
(1)配nameservices
,起个名字
(2)为上述nameservices指定两个机器。
(3)为这个两个机器分别指定rpc端口。
内部rpc端口9000和8020都可以。
HA时的hdfs-site.xml
:
<configuration>
<property>
<name>dfs.nameservicesname>
<value>hadoop-ns1value>
property>
<property>
<name>dfs.replicationname>
<value>3value>
property>
<property>
<name>dfs.namenode.name.dirname>
<value>file:///home/hadoop/data/dfs/nnvalue>
property>
<property>
<name>dfs.datanode.data.dirname>
<value>file:///home/hadoop/data/dfs/dnvalue>
property>
<property>
<name>dfs.ha.namenodes.hadoop-ns1name>
<value>nn1,nn2value>
property>
<property>
<name>dfs.namenode.rpc-address.hadoop-ns1.nn1name>
<value>hadoop-master1:8020value>
property>
<property>
<name>dfs.namenode.http-address.hadoop-ns1.nn1name>
<value>hadoop-master1:50070value>
property>
<property>
<name>dfs.namenode.rpc-address.hadoop-ns1.nn2name>
<value>hadoop-master2:8020value>
property>
<property>
<name>dfs.namenode.http-address.hadoop-ns1.nn2name>
<value>hadoop-master2:50070value>
property>
<property>
<name>dfs.namenode.shared.edits.dirname>
<value>qjournal://hadoop-slave1:8485;hadoop-slave2:8485;hadoop-slave3:8485/hadoop-ns1value>
property>
<property>
<name>dfs.journalnode.edits.dirname>
<value>/home/hadoop/data/journalvalue>
property>
<property>
<name>dfs.client.failover.proxy.provider.hadoop-ns1name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvidervalue>
property>
<property>
<name>dfs.ha.fencing.methodsname>
<value>sshfencevalue>
property>
<property>
<name>dfs.ha.fencing.ssh.private-key-filesname>
<value>/home/hadoop/.ssh/id_rsavalue>
property>
<property>
<name>dfs.ha.fencing.ssh.connect-timeoutname>
<value>30000value>
property>
<property>
<name>dfs.ha.automatic-failover.enabledname>
<value>falsevalue>
property>
configuration>
上述failover没有zk时不用开启。上述配置了journalnode集群,通过命令启动即可。
上述配置中,格式化namenode(仅第一次),在启动三台journalnode,再在master1上启动namenode:
#格式化namenode(仅首次)
[hadoop-master1]$ hadoop namenode -format
#启动jouenalnode
[hadoop-slave1]$ hadoop-daemon.sh start journalnode
[hadoop-slave2]$ hadoop-daemon.sh start journalnode
[hadoop-slave3]$ hadoop-daemon.sh start journalnode
#启动一个namenode
[hadoop-master1]$ hadoop-daemon.sh start namenode
看到一个节点的master已经启动,不过是standby模式。
此时还不能访问hdfs文件系统。需要启动active namenode。
nn2在格式化时,不能再使用相同的命令,要使用standby将nn1的同步过来:
# 格式化nn2(仅首次),但是不能同nn1一样命令
[hadoop-master2] $ hadoop namenode -bootstrapStandby
#启动namenode
[hadoop-master2] $ hadoop-daemon.sh start namenode
启动namenode后,hadoop-naster2也有namenode进程。
hadoop-master2此时也是standby状态。
【启动active】
from master2 to master1 将1变成active:
[hadoop@hadoop-master1]$ hdfs haadmin -failover --forceactive nn2 nn1
2019-07-13 17:45:35,815 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Failover from nn2 to nn1 successful
注意:不能将上述nn1,nn2写成主机名,否则不能识别。
nn1,nn2是在hdfs-site.xml中配置的引用。
此时hadoop-master1变成active:
启动其他机器的datanode。
1、注意:namenode format
只能进行一次!不小心在slave上format
后,导致集群VERSION
文件中的cluster_Id
对应不上,datanode不能起起来。
2、通过NN或DN的启动日志来排查。
关闭active的NN,直接stop或者kill:
[hadoop@hadoop-master1]$ hadoop-daemon.sh stop namenode
此时已经不能再操作hdfs文件系统。如hadoop fs -ls /
等。
我们通过命令将master2激活:
[hadoop@hadoop-master1 test]$ hdfs haadmin -failover --forceactive nn1 nn2
2019-07-13 19:25:08,044 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
2019-07-13 19:25:09,195 INFO ipc.Client: Retrying connect to server: hadoop-master1/10.179.83.24:8020. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS)
2019-07-13 19:25:09,198 WARN ha.FailoverController: Unable to gracefully make NameNode at hadoop-master1/10.179.83.24:8020 standby (unable to connect)
java.net.ConnectException: Call From hadoop-master1/10.179.83.24 to hadoop-master1:8020 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
报错链接补上master1,因为已经关闭了master1,正常。
此时,访问hdfs正常。
zk自动方式,待补充。。。