Namenode HA原理以及配置

NameNode HA 原理
hadoop2.x之后,Clouera提出了QJM/Qurom Journal Manager.

这是一个基于Paxos算法实现的HDFS HA方案,它给出了一种较好的解决思路和方案,示意图如下:

Namenode HA原理以及配置

• QJM方式来实现HA的原理:
• 基本原理就是用2N+1台 JN 存储EditLog,每次写数据操作有大多数(>=N+1)返回成功时即认为该次写成功,数据不会丢失了。当然这个算法所能容忍的是最多有N台机器挂掉,如果多于N台挂掉,这个算法就失效了。这个原理是基于Paxos算法
• 在HA架构里面SecondaryNameNode这个冷备角色已经不存在了,为了保持standby NN时时的与主Active NN的元数据保持一致,他们之间交互通过一系列守护的轻量级进程JournalNode
• 任何修改操作在 Active NN上执行时,JN进程同时也会记录修改log到至少半数以上的JN中,这时 Standby NN 监测到JN 里面的同步log发生变化了会读取 JN 里面的修改log,然后同步到自己的的目录镜像树里面,如下图:

Namenode HA原理以及配置

• 当发生故障时,Active的 NN 挂掉后,Standby NN 会在它成为Active NN 前,读取所有的JN里面的修改日志,这样就能高可靠的保证与挂掉的NN的目录镜像树一致,然后无缝的接替它的职责,维护来自客户端请求,从而达到一个高可用的目的

• QJM方式来实现HA的主要优势:
1. 不需要配置额外的高共享存储,降低了复杂度和维护成本
2. 消除spof(single point of failure)
3. 系统鲁棒性(Robust:健壮)的程度是可配置
4. JN不会因为其中一台的延迟而影响整体的延迟,而且也不会因为JN的数量增多而影响性能(因为NN向JN发送日志是并行的)


NameNode HA 详解
datanode的fencing
: 确保只有一个NN能命令DN。HDFS-1972中详细描述了DN如何实现fencing
1. 每个NN改变状态的时候,向DN发送自己的状态和一个***
2. DN在运行过程中维护此***,当failover时,新的NN在返回DN心跳时会返回自己的active状态和一个更大的***。DN接收到这个返回则认为该NN为新的active
3. 如果这时原来的active NN恢复,返回给DN的心跳信息包含active状态和原来的***,这时DN就会拒绝这个NN的命令

客户端fencing
确保只有一个NN能响应客户端请求,让访问standby nn的客户端直接失败。在RPC层封装了一层,通过FailoverProxyProvider以重试的方式连接NN。通过若干次连接一个NN失败后尝试连接新的NN,对客户端的影响是重试的时候增加一定的延迟。客户端可以设置重试此时和时间

Hadoop提供了ZKFailoverController角色,部署在每个NameNode的节点上,作为一个deamon进程, 简称zkfc,示例图如下:

Namenode HA原理以及配置

FailoverController主要包括三个组件:
1. HealthMonitor: 监控NameNode是否处于unavailable或unhealthy状态。当前通过RPC调用NN相应的方法完成
2. ActiveStandbyElector: 管理和监控自己在ZK中的状态
3. ZKFailoverController: 它订阅HealthMonitor 和ActiveStandbyElector 的事件,并管理NameNode的状态

ZKFailoverController主要职责:
1. 健康监测:周期性的向它监控的NN发送健康探测命令,从而来确定某个NameNode是否处于健康状态,如果机器宕机,心跳失败,那么zkfc就会标记它处于一个不健康的状态
2. 会话管理:如果NN是健康的,zkfc就会在zookeeper中保持一个打开的会话,如果NameNode同时还是Active状态的,那么zkfc还会在Zookeeper中占有一个类型为短暂类型的znode,当这个NN挂掉时,这个znode将会被删除,然后备用的NN,将会得到这把锁,升级为主NN,同时标记状态为Active
3. 当宕机的NN新启动时,它会再次注册zookeeper,发现已经有znode锁了,便会自动变为Standby状态,如此往复循环,保证高可靠,需要注意,目前仅仅支持最多配置2个NN
4. master选举:如上所述,通过在zookeeper中维持一个短暂类型的znode,来实现抢占式的锁机制,从而判断那个NameNode为Active状态


NameNode HA 配置

一、服务器分布

服务角色\服务器 10.124.151.18(hadoop1) 10.124.151.19(hadoop2) 10.124.151.20(hadoop3) 10.124.151.22(hadoop4)
NameNode YES YES NO NO
DataNode NO NO YES YES
JournalNode YES YES YES NO
Zookeeper YES YES YES NO
ZKFC YES YES NO NO


二、基础环境部署
1.时间同步。

使用ntpdata加入到定时任务,或者ntpd服务都可以。最终时间一致即可。

2.主机名设置,并添加至/etc/hosts中。
10.124.151.18 hadoop1
10.124.151.19 hadoop2
10.124.151.20 hadoop3
10.124.151.22 hadoop4


3.jdk安装。
过程略,最终结果如下:
[[email protected] ~]# java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)


4.添加用户
使用hadoop用户管理hadoop。
[[email protected] ~]# useradd hadoop
useradd: user 'hadoop' already exists
[[email protected] ~]# echo hadoop123 | passwd --stdin hadoop
Changing password for user hadoop.
passwd: all authentication tokens updated successfully.


5.免密配置。
切换到hadoop配置免密:
[[email protected] ~]$ ssh-******
[[email protected] ~]$ ssh-copy-id [email protected]

拷贝.ssh目录到其他三台主机的hadoop用户的家目录下:
[[email protected] ~]$ scp -r ~/.ssh [email protected]:~/
[[email protected] ~]$ scp -r ~/.ssh [email protected]:~/
[[email protected] ~]$ scp -r ~/.ssh [email protected]:~/
免密配置完成。

三、部署zookeeper

这个不做详细解释。百度下应该很简单就搞定,之后再单独写一个zookeeper集群搭建的文章。


四、安装配置hadoop
1.下载安装包,下面网址是清华的镜像站点,选择版本下载即可。

http://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/
这里我们使用hadoop-2.7.3.tar.gz版本

将安装包上传至10.124.151.18机器上,解压至/app下。
[[email protected] ~]$ tar -xvf hadoop-2.7.3.tar.gz -C /app/

2.修改配置(因为我这里并不使用YARN,所以只配置和启动HDFS的相关内容)

/app/hadoop/etc/hadoop/hadoop-env.sh文件:

export JAVA_HOME=/usr/java/jdk1.8.0_111
export HADOOP_CONF_DIR=/app/hadoop/etc/hadoop


/app/hadoop/etc/hadoop/core-site.xml文件:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://NameServer</value>
</property>
<!-- 指定hadoop临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/app/hadoop/tmp</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>10.124.151.18:2181,10.124.151.19:2181,10.124.151.20:2181</value>
</property>
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>2000</value>
</property>
</configuration>


/app/hadoop/etc/hadoop/hdfs-site.xml文件:
<configuration>
<!--指定hdfs的nameservice为NameServer,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>NameServer</value>
</property>
<!-- NameServer下面有两个NameNode,分别是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.NameServer</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.NameServer.nn1</name>
<value>10.124.151.18:9000</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.NameServer.nn2</name>
<value>10.124.151.19:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.NameServer.nn1</name>
<value>10.124.151.18:50070</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.NameServer.nn2</name>
<value>10.124.151.19:50070</value>
</property>
<!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://10.124.151.18:8485;10.124.151.19:8485;10.124.151.20:8485/NameServer</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/app/hadoop/tmp/journal</value>
</property>
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置失败自动切换实现方式 -->
<property>
<name>dfs.client.failover.proxy.provider.NameServer</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>
<!--指定namenode名称空间的存储地址 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///app/hadoop/hdfs/name</value>
</property>
<!--指定datanode数据存储地址 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///app/hadoop/hdfs/data</value>
</property>
<!--指定数据冗余份数 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
</configuration>


/app/hadoop/etc/hadoop/slaves文件
10.124.151.20
10.124.151.22


创建配置中相应的目录
mkdir /app/hadoop/tmp
mkdir -p /app/hadoop/hdfs/{name,data}
mkdir -p /app/hadoop/tmp/journal

拷贝/app/hadoop到其他节点
[[email protected] app]$ scp -r hadoop 10.124.151.19:/app/
[[email protected] app]$ scp -r hadoop 10.124.151.20:/app/
[[email protected] app]$ scp -r hadoop 10.124.151.22:/app/


3.启动HDFS
1.创建命名空间
[[email protected] hadoop]$ ./bin/hdfs zkfc -formatZK
2.在对应节点启动journalnode
[[email protected] hadoop]$ ./sbin/hadoop-daemon.sh start journalnode
[[email protected] hadoop]$ ./sbin/hadoop-daemon.sh start journalnode
[[email protected] hadoop]$ ./sbin/hadoop-daemon.sh start journalnode
3.格式化主NameNode节点
[[email protected] hadoop]$ ./bin/hdfs namenode -format
4.启动主NameNode节点
[[email protected] hadoop]$ cd /app/hadoop/ && sbin/hadoop-daemon.sh start namenode
5.格式化备NameNode节点
[[email protected] hadoop]$ ./bin/hdfs namenode -bootstrapStandby
6.启动备NameNode节点
[[email protected] hadoop]$ cd /app/hadoop/ && sbin/hadoop-daemon.sh start namenode
7.在主备NameNode节点启动ZKFC
[[email protected] hadoop]$ cd /app/hadoop/ && sbin/hadoop-daemon.sh start zkfc
[[email protected] hadoop]$ cd /app/hadoop/ && sbin/hadoop-daemon.sh start zkfc
8.启动所有DataNode节点
[[email protected] app]$ cd /app/hadoop/ && sbin/hadoop-daemon.sh start datanode
[[email protected] app]$ cd /app/hadoop/ && sbin/hadoop-daemon.sh start datanode


启动完成使用jps命令查看,可以看到和规划的一致。

Namenode HA原理以及配置


查看namenode状态
浏览器访问10.124.151.18:50070 如下:(可以看到是active状态,为主)

Namenode HA原理以及配置

浏览器访问10.124.151.19:50070 如下:(可以看到是standby状态,为备)

Namenode HA原理以及配置

4.测试NameNode HA的failover

杀掉主节点的namenode进程如下:

[[email protected] hadoop]$ jps
5252 QuorumPeerMain
8021 NameNode
8220 DFSZKFailoverController
8686 Jps
7710 JournalNode
[[email protected] hadoop]$ kill -9
8021

查看备节点的状态,如下图所示(可以看到备节点变成active)

Namenode HA原理以及配置

再次启动原来的主节点,查看状态如下图(原来的主节点变为standby)

Namenode HA原理以及配置

经测试NameNode的HA配置成功。

此文章只配置了HDFS的相关配置,如有yarn需求和mapred需求则配置相应的配置文件启动即可。不做赘述。