双 NameNode(HA)实现原理
双NN出现背景
在 Hadoop1.x 版本中,HDFS 只支持一个 NameNode,为了保证稳定性,只能靠 SecondaryNameNode 来实现,而 SecondaryNameNode 不能做到热备,而且恢复的数据也不是最新的元数据。基于此,从 Hadoop2.x 版本开始,HDFS 开始支持多个 NameNode,这样不但可以实现 HDFS 的高可用性(HA,High Availability),而且还可以横行扩容 HDFS 的存储规模。
故而在实际的企业应用中,使用最多的是双 NameNode 架构,也就是一个 NameNode 处于 Active(活跃) 状态,另一个 NameNode 处于 Standby(备用)状态,通过这种机制,实现 NameNode 的双机热备高可用功能。
双 NameNode 的运行原理
在高可用的 NameNode 体系结构中,只有 Active 状态的 NameNode 是正常工作的,Standby 状态的 NameNode 处于随时待命状态,它时刻去同步 Active 状态 NameNode 的元数据。一旦 Active 状态的 NameNode 不能工作,可以通过手工或者自动切换方式将 Standby 状态的 NameNode 转变为 Active 状态,保持 NameNode 持续工作。这就是两个高可靠的 NameNode 的实现机制。
NameNode 主、备之间的切换可以通过手动或者自动方式来实现,作为线上大数据环境,都是通过自动方式来实现切换的,为保证自动切换,NameNode 使用 ZooKeeper 集群进行仲裁选举。基本的思路是 HDFS 集群中的两个 NameNode 都在 ZooKeeper 中注册,当 Active 状态的 NameNode 出故障时,ZooKeeper 能马上检测到这种情况,它会自动把 Standby 状态切换为 Active 状态。
ZooKeeper(ZK)集群作为一个高可靠系统,能够为集群协作数据提供监控,并将数据的更改随时反馈给客户端。HDFS 的热备功能依赖 ZK 提供的两个特性:错误监测、活动节点选举。HDFS 通过 ZK 实现高可用的机制如下:
每个 NameNode 都会在 ZK 中注册并且持久化一个 session 标识,一旦 NameNode 失效了,那么 session 也将过期,而 ZK 也会通知其他的 NameNode 发起一个失败切换。ZK 提供了一个简单的机制来保证只有一个 NameNode 是活动的,那就是独占锁,如果当前的活动 NameNode 失效了,那么另一个 NameNode 将获取 ZK 中的独占锁,表明自己是活动的节点。
ZKFailoverController(ZKFC)是 ZK 集群的客户端,用来监控 NN 的状态信息,每个运行 NameNode 的节点必须要运行一个 ZKFC。ZKFC 提供以下功能:
健康检查,ZKFC 定期对本地的 NN 发起 health-check 的命令,如果 NN 正确返回,那么 NN 被认为是 OK 的,否则被认为是失效节点;
session管理,当本地 NN 是健康的时候,ZKFC 将会在 ZK 中持有一个 session,如果本地 NN 又正好是 Active,那么 ZKFC 将持有一个短暂的节点作为锁,一旦本地 NN 失效了,那么这个节点就会被自动删除;
基础选举,如果本地 NN 是健康的,并且 ZKFC 发现没有其他 NN 持有这个独占锁,那么它将试图去获取该锁,一旦成功,那么它就开始执行 Failover,然后变成 Active 状态的 NN 节点;Failover 的过程分两步,首先对之前的 NameNode 执行隔离(如果需要的话),然后将本地 NameNode 切换到 Active 状态。
双 NameNode 架构中元数据一致性
从 Hadoop2.x 版本后,HDFS 采用了一种全新的元数据共享机制,即通过 Quorum Journal Node(JournalNode)集群或者 network File System(NFS)进行数据共享。NFS 是操作系统层面的,而 JournalNode 是 Hadoop 层面的,成熟可靠、使用简单方便,所以,这里我们采用 JournalNode 集群进行元数据共享。
JournalNode 集群可以几乎实时的去 NameNode 上拉取元数据,然后保存元数据到 JournalNode 集群;同时,处于 standby 状态的 NameNode 也会实时的去 JournalNode 集群上同步 JNS 数据,通过这种方式,就实现了两个 NameNode 之间的数据同步。
那么,JournalNode 集群内部是如何实现的呢?
两个 NameNode 为了数据同步,会通过一组称作 JournalNodes 的独立进程进行相互通信。当 Active 状态的 NameNode 元数据有任何修改时,会告知大部分的 JournalNodes 进程。同时,Standby 状态的 NameNode 也会读取 JNs 中的变更信息,并且一直监控 EditLog (事务日志)的变化,并把变化应用于自己的命名空间。Standby 可以确保在集群出错时,元数据状态已经完全同步了。
下图是 JournalNode 集群的内部运行架构图。
JN1、JN2、JN3 等是 JournalNode 集群的节点,QJM(Qurom Journal Manager)的基本原理是用 2N+1 台 JournalNode 存储 EditLog,每次写数据操作有 N/2+1 个节点返回成功,那么本次写操作才算成功,保证数据高可用。当然这个算法所能容忍的是最多有 N 台机器挂掉,如果多于 N 台挂掉,算法就会失效。
ANN 表示处于 Archive 状态的 NameNode,SNN 表示处于 Standbye 状态的 NameNode,QJM 从 ANN 读取数据写入 EditLog 中,然后 SNN 从 EditLog 中读取数据,进而应用到自身。
双 NameNode 高可用 Hadoop 集群架构
下图是一个高可用的 Hadoop 集群运行原理图。
此架构主要解决了两个问题,一是 NameNode 元数据同步问题,二是主备 NameNode 切换问题,由图可知,解决主、备 NameNode 元数据同步是通过 JournalNode 集群来完成的,而解决主、备 NameNode 切换可通过 ZooKeeper 来完成。
群来完成的,而解决主、备 NameNode 切换可通过 ZooKeeper 来完成。
ZooKeeper 是一个独立的集群,在两个 NameNode 上还需要启动一个 failoverController(zkfc)进程,该进程作为 ZooKeeper 集群的客户端存在,通过 zkfc 可以实现与 ZooKeeper 集群的交互和状态监测。
原文地址:https://blog.csdn.net/qq_45674835/article/details/107436350