Hadoop系列(八)——基于ZooKeeper搭建Hadoop高可用集群

一、高可用简介

Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求比 YARN ResourceManger 高得多,所以它的实现也更加复杂,故下面先进行讲解:

创新互联建站专业为企业提供名山网站建设、名山做网站、名山网站设计、名山网站制作等企业网站建设、网页设计与制作、名山企业网站模板建站服务,10余年名山做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

1.1 高可用整体架构

HDFS 高可用架构如下:

Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

图片引用自: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,只有主 NameNode 才能对外提供读写服务。

  • 主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。

  • Zookeeper 集群:为主备切换控制器提供主备选举支持。

  • 共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 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 首先把 EditLog 提交到 JournalNode 集群,然后 Standby NameNode 再从 JournalNode 集群定时同步 EditLog,当 Active NameNode 宕机后, Standby NameNode 在确认元数据完全同步之后就可以对外提供服务。

需要说明的是向 JournalNode 集群写入 EditLog 是遵循 “过半写入则成功” 的策略,所以你至少要有 3 个 JournalNode 节点,当然你也可以继续增加节点数量,但是应该保证节点总数是奇数。同时如果有 2N+1 台 JournalNode,那么根据过半写的原则,最多可以容忍有 N 台 JournalNode 节点挂掉。

Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

1.3 NameNode 主备切换

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

Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

  1. HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测。
  2. HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFailoverController 注册的相应方法进行处理。
  3. 如果 ZKFailoverController 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举。
  4. ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举。
  5. ActiveStandbyElector 在主备选举完成后,会回调 ZKFailoverController 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。
  6. ZKFailoverController 调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。

1.4 YARN高可用

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

Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

二、集群规划

按照高可用的设计目标:需要保证至少有两个 NameNode (一主一备) 和 两个 ResourceManager (一主一备) ,同时为满足“过半写入则成功”的原则,需要至少要有 3 个 JournalNode 节点。这里使用三台主机进行搭建,集群规划如下:

Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

三、前置条件

  • 所有服务器都安装有 JDK,安装步骤可以参见:Linux 下 JDK 的安装;
  • 搭建好 ZooKeeper 集群,搭建步骤可以参见:Zookeeper 单机环境和集群环境搭建
  • 所有服务器之间都配置好 SSH 免密登录。

四、集群配置

4.1 下载并解压

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

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

4.2 配置环境变量

编辑 profile 文件:

# vim /etc/profile

增加如下配置:

export HADOOP_HOME=/usr/app/hadoop-2.6.0-cdh6.15.2
export  PATH=${HADOOP_HOME}/bin:$PATH

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

# source /etc/profile

4.3 修改配置

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

1. hadoop-env.sh
# 指定JDK的安装位置
export JAVA_HOME=/usr/java/jdk1.8.0_201/
2. core-site.xml

    
        
        fs.defaultFS
        hdfs://hadoop001:8020
    
    
        
        hadoop.tmp.dir
        /home/hadoop/tmp
    
    
        
        ha.zookeeper.quorum
        hadoop001:2181,hadoop002:2181,hadoop002:2181
    
    
        
        ha.zookeeper.session-timeout.ms
        10000
    
3. hdfs-site.xml

    
        
        dfs.replication
        3
    
    
        
        dfs.namenode.name.dir
        /home/hadoop/namenode/data
    
    
        
        dfs.datanode.data.dir
        /home/hadoop/datanode/data
    
    
        
        dfs.nameservices
        mycluster
    
    
        
        dfs.ha.namenodes.mycluster
        nn1,nn2
    
    
        
        dfs.namenode.rpc-address.mycluster.nn1
        hadoop001:8020
    
    
        
        dfs.namenode.rpc-address.mycluster.nn2
        hadoop002:8020
    
    
        
        dfs.namenode.http-address.mycluster.nn1
        hadoop001:50070
    
    
        
        dfs.namenode.http-address.mycluster.nn2
        hadoop002:50070
    
    
        
        dfs.namenode.shared.edits.dir
        qjournal://hadoop001:8485;hadoop002:8485;hadoop003:8485/mycluster
    
    
        
        dfs.journalnode.edits.dir
        /home/hadoop/journalnode/data
    
    
        
        dfs.ha.fencing.methods
        sshfence
    
    
        
        dfs.ha.fencing.ssh.private-key-files
        /root/.ssh/id_rsa
    
    
        
        dfs.ha.fencing.ssh.connect-timeout
        30000
    
    
        
        dfs.client.failover.proxy.provider.mycluster
        org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
    
    
        
        dfs.ha.automatic-failover.enabled
        true
    
4. yarn-site.xml

    
        
        yarn.nodemanager.aux-services
        mapreduce_shuffle
    
    
        
        yarn.log-aggregation-enable
        true
    
    
        
        yarn.log-aggregation.retain-seconds
        86400
    
    
        
        yarn.resourcemanager.ha.enabled
        true
    
    
        
        yarn.resourcemanager.cluster-id
        my-yarn-cluster
    
    
        
        yarn.resourcemanager.ha.rm-ids
        rm1,rm2
    
    
        
        yarn.resourcemanager.hostname.rm1
        hadoop002
    
    
        
        yarn.resourcemanager.hostname.rm2
        hadoop003
    
    
        
        yarn.resourcemanager.webapp.address.rm1
        hadoop002:8088
    
    
        
        yarn.resourcemanager.webapp.address.rm2
        hadoop003:8088
    
    
        
        yarn.resourcemanager.zk-address
        hadoop001:2181,hadoop002:2181,hadoop003:2181
    
    
        
        yarn.resourcemanager.recovery.enabled
        true
    
    
        
        yarn.resourcemanager.store.class
        org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore
    
5. mapred-site.xml

    
        
        mapreduce.framework.name
        yarn
    
5. slaves

配置所有从属节点的主机名或 IP 地址,每行一个。所有从属节点上的 DataNode 服务和 NodeManager 服务都会被启动。

hadoop001
hadoop002
hadoop003

4.4 分发程序

将 Hadoop 安装包分发到其他两台服务器,分发后建议在这两台服务器上也配置一下 Hadoop 的环境变量。

# 将安装包分发到hadoop002
scp -r /usr/app/hadoop-2.6.0-cdh6.15.2/  hadoop002:/usr/app/
# 将安装包分发到hadoop003
scp -r /usr/app/hadoop-2.6.0-cdh6.15.2/  hadoop003:/usr/app/

五、启动集群

5.1 启动ZooKeeper

分别到三台服务器上启动 ZooKeeper 服务:

 zkServer.sh start

5.2 启动Journalnode

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

hadoop-daemon.sh start journalnode

5.3 初始化NameNode

hadop001 上执行 NameNode 初始化命令:

hdfs namenode -format

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

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

5.4 初始化HA状态

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

hdfs zkfc -formatZK

5.5 启动HDFS

进入到 hadoop001${HADOOP_HOME}/sbin 目录下,启动 HDFS。此时 hadoop001hadoop002 上的 NameNode 服务,和三台服务器上的 DataNode 服务都会被启动:

start-dfs.sh

5.6 启动YARN

进入到 hadoop002${HADOOP_HOME}/sbin 目录下,启动 YARN。此时 hadoop002 上的 ResourceManager 服务,和三台服务器上的 NodeManager 服务都会被启动:

start-yarn.sh

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

yarn-daemon.sh start resourcemanager

六、查看集群

6.1 查看进程

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

[root@hadoop001 sbin]# jps
4512 DFSZKFailoverController
3714 JournalNode
4114 NameNode
3668 QuorumPeerMain
5012 DataNode
4639 NodeManager

[root@hadoop002 sbin]# jps
4499 ResourceManager
4595 NodeManager
3465 QuorumPeerMain
3705 NameNode
3915 DFSZKFailoverController
5211 DataNode
3533 JournalNode

[root@hadoop003 sbin]# jps
3491 JournalNode
3942 NodeManager
4102 ResourceManager
4201 DataNode
3435 QuorumPeerMain

6.2 查看Web UI

HDFS 和 YARN 的端口号分别为 500708080,界面应该如下:

此时 hadoop001 上的 NameNode 处于可用状态:

Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群
而 hadoop002 上的 NameNode 则处于备用状态:


Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

hadoop002 上的 ResourceManager 处于可用状态:


Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

hadoop003 上的 ResourceManager 则处于备用状态:


Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

同时界面上也有 Journal Manager 的相关信息:


Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

七、集群的二次启动

上面的集群初次启动涉及到一些必要初始化操作,所以过程略显繁琐。但是集群一旦搭建好后,想要再次启用它是比较方便的,步骤如下(首选需要确保 ZooKeeper 集群已经启动):

hadoop001 启动 HDFS,此时会启动所有与 HDFS 高可用相关的服务,包括 NameNode,DataNode 和 JournalNode:

start-dfs.sh

hadoop002 启动 YARN:

start-yarn.sh

这个时候 hadoop003 上的 ResourceManager 服务通常还是没有启动的,需要手动启动:

yarn-daemon.sh start resourcemanager

参考资料

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

  • HDFS High Availability Using the Quorum Journal Manager
  • ResourceManager High Availability

关于 Hadoop 高可用原理的详细分析,推荐阅读:

Hadoop NameNode 高可用 (High Availability) 实现解析

更多大数据系列文章可以参见 GitHub 开源项目大数据入门指南


当前标题:Hadoop系列(八)——基于ZooKeeper搭建Hadoop高可用集群
网站路径:http://pwwzsj.com/article/ghohhp.html