高可用简介

Hadoop的高可用可以分为HDFS高可用和YARN高可用。它们的实现基本相似,但是HDFS NameNode比YARN Resource Manger需要更高的数据存储和一致性,所以它的实现更加复杂。因此,让我们解释以下内容:

1.1 高可用架构

HDFS高可用架构如下:

图片引用自:https://www.edureka.co/blog/how-to-set-up-hadoop-cluster-with-hdfs-high-availability/

HDFS 高可用性架构由以下组件组成:

  • Active NameNode和Standby NameNode:两个NameNode是互为可用的。一个处于Active状态,主NameNode,另一个处于Standby状态。只有主 NameNode 才能对外提供读写服务。

  • ZKFailover Controller:ZKFailover Controller作为一个独立的进程运行,它控制着NameNode的主开关。 ZKFailover Controller可以及时检测NameNode的健康状态,并在主NameNode出现故障时与Zookeeper实现自动备份选举和切换。当然,NameNode 也支持无需 Zookeeper 的手动备份切换。

  • Zookeeper Cluster:为备份切换控制器提供备份选举支持。

  • 共享存储系统:共享存储系统是实现NameNode高可用最关键的部分。共享存储系统保存了 NameNode 在运行过程中产生的 HDFS 的元数据。 Master NameNode和NameNode通过共享存储系统实现元数据同步。在主备切换时,新的主NameNode只有在确认元数据完全同步后才能继续提供服务。

  • DataNode节点:除了通过共享存储系统共享HDFS的元数据信息外,主NameNode和备用NameNode也需要HDFS数据块与DataNode的映射关系。 DataNode 向主 NameNode 和备用 NameNode 上报数据块的位置信息。

1.2 基于QJM的共享存储系统数据同步机制分析

目前,Hadoop 支持使用 Quorum Journal Manager (QJM) 或 Network File System (NFS) 作为共享存储系统。本文以QJM集群为例进行说明:Active NameNode首先向Journal Node集群提交EditLog,然后Standby NameNode从Journal Node集群同步EditLog,当A的active NameNode宕机后,Standby NameNode可以对外提供服务确认元数据已完全同步。

需要注意的是,将EditLog写入JournalNode集群遵循“过半写入成功”的策略,因此至少需要三个JournalNode节点。当然,你可以继续增加节点数,但要保证总节点数为奇数。同时,如果有2N+1个JournalNode,那么按照过半写的原则,最多可以容忍N个JournalNode节点挂掉。

1.3 NameNode主备切换

NameNode的主备切换流程如下图所示:

  1. Health Monitor初始化完成后,启动内部线程周期性调用NameNode的HASERVICE Protocol RPC接口对应的方法,检测NameNode的健康状态。

2、如果Health Monitor检测到NameNode的健康状态发生变化,则回调ZKFailover Controller注册的相应方法进行处理。

3、如果ZKFailover Controller判断需要主备切换,会先使用Active Standby Elector进行自动主选举。

  1. Active Standby选举人与Zookeeper交互,完成一次自动备份选举。

5、Active Standby Elector回调ZKFailover Controller的相应方法,通知当前NameNode在主选举完成后成为主NameNode或备用NameNode。

6、ZKFailover Controller调用NameNode对应的HASERVICE Protocol RPC接口,将NameNode转换为Active或Standby状态。

1.4 YARN 高可用

YARN Resource Manager 的高可用类似于 HDFS NameNode 的高可用。但是与NameNode不同的是,ResourceManager没有那么多元数据信息需要维护,所以它的状态信息可以直接写入Zookeeper,依赖Zookeeper进行主备选举。

二.集群规划

按照高可用的设计目标,至少需要保证2个NameNode和2个ResourceManager,同时至少需要3个Journal Node,才能满足“过半写入成功”的原则。三台主机用于构建集群。集群规划如下:

前置条件

  • JDK安装在所有服务器上。安装步骤可以看如下:Linux下JDK的安装;

  • 搭建ZooKeeper集群,步骤可以看如下:Zookeeper单机环境和集群环境搭建

  • 所有服务器之间配置SSH免密登录。

四.集群配置

4.1 下载解压

下载 Hadoop。这里我下载了CDH版本的Hadoop,下载地址是:http://archive.cloudera.com/cdh5/cdh/5/

# tar -zvxf hadoop-2.6.0-cdh5.15.2.tar.gz

4.2 配置环境变量

编辑配置文件:

# vim /etc/profile

添加以下配置:

导出 HADOOP_HOMEu003d/usr/app/hadoop-2.6.0-cdh5.15.2

导出 PATHu003d${HADOOP_HOME}/bin:$PATH

执行source命令使配置立即生效:

# 源 /etc/profile

4.3 配置修改

进入 ${HADOOP_HOME}/etc/hadoop 目录,修改配置文件。每个配置文件的内容如下:

1. hadoop-env.sh

# 指定JDK的安装位置

导出 JAVA_HOMEu003d/usr/java/jdk1.8.0_201/

2.核心站点.xml

<配置>

<属性>

<!-- 指定namenode的hdfs协议文件系统通信地址-->

<name>fs.defaultFS</name>

<value>hdfs://hadoop001:8020</value>

</属性>

<属性>

<!-- 指定hadoop集群中存储的临时文件目录 -->

<name>hadoop.tmp.dir</name>

<值>/home/hadoop/tmp</值>

</属性>

<属性>

<!-- 集群的 ZooKeeper 地址 -->

<name>ha.zookeeper.quorum</name>

<value>hadoop001:2181,hadoop002:2181,hadoop002:2181</value>

</属性>

<属性>

<!-- ZKFC 连接到 ZooKeeper 超时持续时间 -->

<name>ha.zookeeper.session-timeout.ms</name>

<值>10000</值>

</属性>

</配置>

3. hdfs-site.xml

<配置>

<属性>

<!-- 指定HDFS副本数-->

<name>dfs.replication</name>

<值>3</值>

</属性>

<属性>

<!-- namenode 节点数据(即元数据)的存储位置,可以指定多个目录进行容错,多个目录之间用逗号分隔。 -->

<name>dfs.namenode.name.dir</name>

<value>/home/hadoop/namenode/data</value>

</属性>

<属性>

<!-- datanode 节点数据(即数据块)的存储位置 -->

<name>dfs.datanode.data.dir</name>

<value>/home/hadoop/datanode/data</value>

</属性>

<属性>

<!-- 集群服务的逻辑名-->

<name>dfs.nameservices</name>

<value>我的集群</value>

</属性>

<属性>

<!-- NameNode ID 列表-->

<name>dfs.ha.namenodes.mycluster</name>

<value>nn1,nn2</value>

</属性>

<属性>

<!-- nn1 的 RPC 邮件地址 -->

<name>dfs.namenode.rpc-address.mycluster.nn1</name>

<value>hadoop001:8020</value>

</属性>

<属性>

<!-- nn2 的 RPC 邮件地址 -->

<name>dfs.namenode.rpc-address.mycluster.nn2</name>

<value>hadoop002:8020</value>

</属性>

<属性>

<!-- nn1 的http 邮件地址-->

<name>dfs.namenode.http-address.mycluster.nn1</name>

<value>hadoop001:50070</value>

</属性>

<属性>

<!-- nn2 的http 邮件地址-->

<name>dfs.namenode.http-address.mycluster.nn2</name>

<value>hadoop002:50070</value>

</属性>

<属性>

<!-- NameNode Metadata in JournalNode 共享存储目录上 -->

<name>dfs.namenode.shared.edits.dir</name>

<value>qjournal://hadoop001:8485;hadoop002:8485;hadoop003:8485/mycluster</value>

</属性>

<属性>

<!-- 期刊编辑文件存储目录-->

<name>dfs.journalnode.edits.dir</name>

<value>/home/hadoop/journalnode/data</value>

</属性>

<属性>

<!-- 配置隔离机制,保证任何时候只有一个NameNode处于活动状态-->

<name>dfs.ha.fencing.methods</name>

<value>sshfence</value>

</属性>

<属性>

<!-- 使用 sshfence 需要的机制 ssh 隐私免费登录 -->

<name>dfs.ha.fencing.ssh.private-key-files</name>

<值>/root/.ssh/id_rsa</值>

</属性>

<属性>

<!-- SSH 超时 -->

<name>dfs.ha.fencing.ssh.connect-timeout</name>

<值>30000</值>

</属性>

<属性>

<!-- 访问代理类判断当前状态Active State NameNode -->

<name>dfs.client.failover.proxy.provider.mycluster</name>

<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

</属性>

<属性>

<!-- 开启自动故障转移 -->

<name>dfs.ha.automatic-failover.enabled</name>

<值>真</值>

</属性>

</配置>

4.纱线站点.xml

<配置>

<属性>

<!--配置NodeManager上运行的Accessory服务。需要配置 mapreduce_shuffle 才可以 Yarn Up 操作 MapReduce 程序。-->

<name>yarn.nodemanager.aux-services</name>

<value>mapreduce_shuffle</value>

</属性>

<属性>

<!-- 是否开启日志聚合(可选)-->

<name>yarn.log-aggregation-enable</name>

<值>真</值>

</属性>

<属性>

<!-- 聚合日志的存储时间(可选)-->

<name>yarn.log-aggregation.retain-seconds</name>

<值>86400</值>

</属性>

<属性>

<!-- 启用 RM HA -->

<name>yarn.resourcemanager.ha.enabled</name>

<值>真</值>

</属性>

<属性>

<!-- RM 集群标识符 -->

<name>yarn.resourcemanager.cluster-id</name>

<value>我的纱线集群</value>

</属性>

<属性>

<!-- RM 逻辑 ID 列表 -->

<name>yarn.resourcemanager.ha.rm-ids</name>

<值>rm1,rm2</值>

</属性>

<属性>

<!-- RM1 服务地址 -->

<name>yarn.resourcemanager.hostname.rm1</name>

<value>hadoop002</value>

</属性>

<属性>

<!-- RM2 服务地址 -->

<name>yarn.resourcemanager.hostname.rm2</name>

<value>hadoop003</value>

</属性>

<属性>

<!-- RM1 应用程序的网址 -->

<name>yarn.resourcemanager.webapp.address.rm1</name>

<value>hadoop002:8088</value>

</属性>

<属性>

<!-- RM2 申请网址 -->

<name>yarn.resourcemanager.webapp.address.rm2</name>

<value>hadoop003:8088</value>

</属性>

<属性>

<!-- 集群的 ZooKeeper 地址 -->

<name>yarn.resourcemanager.zk-address</name>

<value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>

</属性>

<属性>

<!-- 开启自动恢复 -->

<name>yarn.resourcemanager.recovery.enabled</name>

<值>真</值>

</属性>

<属性>

<!-- 持久存储类 -->

<name>yarn.resourcemanager.store.class</name>

<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>

</属性>

</配置>

5. mapred-site.xml

<配置>

<属性>

<!--指定mapreduce作业在yarn upper-->

<name>mapreduce.framework.name</name>

<值>纱线</值>

</属性>

</配置>

5.奴隶

配置所有下级节点的主机名或IP地址,每行一个。启动所有依赖节点上的DataNode服务和NodeManager服务。

hadoop001

hadoop002

hadoop003

4.4 分发程序

Hadoop安装包分发到另外两台服务器,建议两台服务器都配置Hadoop环境变量。

# 安装包分发到Hadoop 002

scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/hadoop002:/usr/app/

分发安装包到Hadoop 003

scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/hadoop003:/usr/app/

五、启动集群

5.1 启动ZooKeeper

在三台服务器上启动 ZooKeeper 服务:

zkServer.sh 启动

5.2 启动日志节点

在三台服务器的${HADOOP_HOME}/sbin目录下启动journalnode进程:

hadoop-daemon.sh 启动日志节点

5.3 初始化NameNode

在hadop001上执行NameNode初始化命令:

hdfs 名称节点-格式

执行初始化命令后,需要将NameNode元数据目录的内容复制到其他未格式化的NameNode。元数据存储目录是hdfs-site.xml中的dfs.namenode.name.dir属性指定的目录。这里我们需要将其复制到 Hadoop 002:

scp -r /home/hadoop/namenode/data hadoop002:/home/hadoop/namenode/

5.4 HA状态的初始化

在任何 NameNode 上使用以下命令来初始化 ZooKeeper 中的 HA 状态:

hdfs zkfc -formatZK

5.5 启动HDFS

进入Hadoop 001的${HADOOP_HOME}/sbin目录,启动HDFS。此时会启动hadoop001和hadoop002上的NameNode服务以及三台服务器上的DataNode服务:

开始-dfs.sh

5.6 启动YARN

进入 Hadoop 002 的 ${HADOOP_HOME}/sbin 目录并启动 YARN。此时会启动hadoop002上的ResourceManager服务和三台服务器上的NodeManager服务:

启动-yarn.sh

需要注意的是,此时hadoop003上的ResourceManager服务通常是没有启动的,需要手动启动:

yarn-daemon.sh 启动资源管理器

6.查看集群

6.1 查看进程

启动成功后,每台服务器上的进程应该如下:

[root@hadoop001 sbin]# jps

4512 DFSZK故障转移控制器

3714 日志节点

4114 名称节点

3668 QuorumPeerMain

5012 数据节点

4639 节点管理器

[root@hadoop002 sbin]# jps

4499 资源管理器

4595 节点管理器

3465 QuorumPeerMain

3705 名称节点

3915 DFSZK故障转移控制器

5211 数据节点

3533 日志节点

[root@hadoop003 sbin]# jps

3491 日志节点

3942 节点管理器

4102 资源管理器

4201 数据节点

3435 QuorumPeerMain

6.2 查看网页界面

HDFS和YARN的端口号分别是50070和8080。界面应该如下:

Hadoop 001 上的 NameNode 目前可用:

Hadoop 002 上的 NameNode 处于待机状态:

<br/>

<br/>

Hadoop 002 上的资源管理器可用:

<br/>

! zoz100076](https://programming.vip/images/doc/0e56504d2610a34abcb91aa15b1eb146.jpg)

<br/>

hadoop003上的ResourceManager处于待机状态:

<br/>

<br/>

同时,界面中还有Journal Manager的相关信息:

<br/>

七.集群二次启动

上面集群的初始启动涉及到一些必要的初始化操作,所以过程略显繁琐。但是一旦集群搭建好了,再启动起来也很方便。步骤如下(首先确保ZooKeeper集群已经启动):

在Hadoop 001中启动HDFS时,会启动所有与HDFS相关的服务,包括NameNode、DataNode和JournalNode:

开始-dfs.sh

在 Hadoop 002 启动 YARN:

启动-yarn.sh

此时hadoop003上的ResourceManager服务通常没有启动,需要手动启动:

yarn-daemon.sh 启动资源管理器

参考资料

以上步骤主要参考官方文档:

  • 使用 Quorum Journal Manager 的 HDFS 高可用性

  • ResourceManager 高可用性

Hadoop高可用原理的详细分析,请阅读:

Hadoop NameNode 高可用实现解析

更多大数据系列文章见GitHub开源项目:大数据介绍指南

Logo

华为、百度、京东云现已入驻,来创建你的专属开发者社区吧!

更多推荐