日志

Hadoop NameNode 高可用架构

NameNode是HDFS(hadoop分布式文件系统)的核心组件,在hadoop 1.x中NameNode存在SPOF(单点故障)问题,NameNode存储了HDFS的元数据信息,一旦NameNode宕机那么整个HDFS就无法访问,依赖HDFS的服务也会被波及(HBase、Hive…)同样无法访问,整个集群陷入瘫痪。NameNode的单点故障问题也使得Hadoop在1.x时代一直都只能用作离线存储和离线计算,无法满足对高可用要求很高的应用场景。Hadoop2.x针对NameNode的SPOF问题提出了高可用架构方案(HA),目前已经能在生产环境下应用。本文主要介绍该高可用架构的主备切换机制。

一、NameNode高可用架构

Hadoop NameNode高可用架构

Hadoop NameNode高可用架构

二、组件概述

Active NameNode 与 Standby NameNode

在NameNode的HA方案中有两个不同状态的NameNode,分别为活跃态(Active)和后备态(Standby),其中只有Active NameNode能对外提供服务,Standby NameNode会根据Active NameNode的状态变化,在必要时可切换成Active.

ZKFC

ZKFC即ZKFailoverController,是基于Zookeeper的故障转移控制器,它负责控制NameNode的主备切换,ZKFC会监测NameNode的健康状态,当发现Active NameNode出现异常时会通过Zookeeper进行一次新的选举,完成Active和Standby状态的切换

HealthMonitor

周期性调用NameNode的HAServiceProtocol RPC接口(monitorHealth 和 getServiceStatus),监控NameNode的健康状态并向ZKFC反馈

ActiveStandbyElector

接收ZKFC的选举请求,通过Zookeeper自动完成主备选举,选举完成后回调ZKFC的主备切换方法对NameNode进行Active和Standby状态的切换.

DataNode

NameNode包含了HDFS的元数据信息和数据块信息(blockmap),其中数据块信息通过DataNode主动向Active NameNode和Standby NameNode上报

共享存储系统

共享存储系统负责存储HDFS的元数据(EditsLog),Active NameNode(写入)和 Standby NameNode(读取)通过共享存储系统实现元数据同步,在主备切换过程中,新的Active NameNode必须确保元数据同步完成才能对外提供服务

三、主备切换流程

① 监控状态

HealthMonitor调用NameNode的RPC方法monitorHealth监控NameNode的健康状态,包括

  • INITIALIZING:HealthMonitor正在启动中,未开始监控
  • HEALTH_MONITOR_FAILED:HealthMonitor运行出错,触发ZKFC的fatalError,ZKFC进程退出
  • SERVICE_NOT_RESPONDING:调用NameNode的monitorHealth方法无响应
  • SERVICE_UNHEALTHY:NameNode正在运行,但NameNode健康检查失败,抛出HealthCheckFailedException异常
  • SERVICE_HEALTHY:NameNode正常运行

HealthMonitor调用NameNode的RPC方法getServiceStatus监控NameNode的角色状态,包括

  • INITIALIZING:NameNode正在启动中
  • ACTIVE:NameNode当前为Active NameNode
  • STANDBY:NameNode当前为Standby NameNode
  • STOPPING:NameNode已经停止
② 状态变化回调

当NameNode的健康状态或角色状态发生变化时,HealthMonitor会回调ZKFC注册的回调方法,ZKFC根据状态的变化决定是否需要进行选举

③ 需要主备选举

NameNode的健康状态(state)变化在主备选举中起核心作用,ZKFC在不同状态下的决策:

  • SERVICE_HEALTHY:NameNode有资格进行主备选举,调用ActiveStandbyElector的joinElection发起一次主备选举
  • SERVICE_NOT_RESPONDINGSERVICE_UNHEALTHY:NameNode不适合成为Active NameNode,调用quitElection(true)从Zookeeper上删除已经建立的临时节点退出主备选举,并进行隔离
  • INITIALIZING:HealthMonitor未开始监控,调用quitElection(false)从Zookeeper上删除已经建立的临时节点退出主备选举,不需要隔离

NameNode的角色状态(status)变化在主备选举中起辅佐作用,ZKFC会比较NameNode的最新角色和自己期望的角色是否一致,如果不一致则调用quitElection退出主备选举

④ 通过zk进行主备选举

ZKFC通过ActiveStandbyElector的joinElection发起NameNode的主备选举,这个过程利用了Zookeeper的写一致性和临时节点机制:

  1. 当发起一次主备选举时,Zookeeper会尝试创建临时节点ActiveStandbyElectorLock,如果创建成功则表示该NameNode竞选Active成功,否则视为竞选失败,最后会通知ZKFC
  2. 不管竞选是否成功(有且只有一个NameNode竞选成功),所有ActiveStandbyElector都会向Zookeeper注册一个watcher用于监听临时节点ActiveStandbyElectorLock的NodeDelete事件
  3. 当调用quitElection退出主备选举或Active NameNode由于宕机使临时节点ActiveStandbyElectorLock被Zookeeper自动删除时就会触发NodeDeleted事件,Standby NameNode会再次尝试创建ActiveStandbyElectorLock,一旦创建成功则该Standby NameNode竞选Active成功,最后通知ZKFC

防止脑裂:
在分布式系统中脑裂又称为双主现象,由于Zookeeper的“假死”可能会导致出现两个NameNode同时为Active状态,此时两个NameNode都可以对外提供服务,无法保证数据一致性。ActiveStandbyElector通过隔离(Fencing)机制防止脑裂现象。
当某个NameNode竞选成功,成功创建ActiveStandbyElectorLock临时节点后会创建另一个名为ActiveBreadCrumb的持久节点,该节点保存了NameNode的地址信息,正常情况下删除ActiveStandbyElectorLock节点时会主动删除ActiveBreadCrumb,但如果由于异常情况导致Zookeeper Session关闭,此时临时节点ActiveStandbyElectorLock会被删除,但持久节点ActiveBreadCrumb并不会删除,当有新的NameNode竞选成功后它会发现已经存在一个旧的NameNode遗留下来的ActiveBreadCrumb节点,此时会通知ZKFC

⑤ 通知ZKFC主备选举结果

主备选举结束后ZKFC会收到ActiveStandbyElector反馈的选举结果,包括:竞选Active成功、竞选Active失败、发现旧的Active NameNode遗留的ActiveBreadCrumb等

⑥ 切换主备状态

收到主备选举结果后ZKFC会根据选举结果进行NameNode的Active和Standby状态变更:

  1. 竞选Active成功:回调NameNode的 transitionToActive 方法使其成为Active状态
  2. 竞选Active失败:回调NameNode的 transitionToStandby 方法使其成为Standby状态
  3. 发现遗留ActiveBreadCrumb:调用 fenceOldActive 方法隔离旧的Active NameNode(首先尝试把它设为Standby,不行就ssh到目标机器上杀死进程或执行自定义的shell进行隔离),只有成功隔离后新的NameNode才会被设为Active状态并对外提供服务
转载请注明出处:

© http://hejunhao.me