NameNode的ZKFC机制

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: 转自: http://hackershell.cn/?p=821   NameNode的HA可以个人认为简单分为共享editLog机制和ZKFC对NameNode状态的控制 在此之前,我先提几个问题: 一般导致NameNode切换的原因 ZKFC的作用是什么?如何判断一个NN...

转自: http://hackershell.cn/?p=821

 

NameNode的HA可以个人认为简单分为共享editLog机制和ZKFC对NameNode状态的控制

在此之前,我先提几个问题:

  • 一般导致NameNode切换的原因

  • ZKFC的作用是什么?如何判断一个NN是否健康

  • NameNode HA是如何实现的?

  • NameNode因为断电导致不能切换的原理,怎样进行恢复

一般导致NameNode切换的原因

随着集群规模的变大和任务量变多,NameNode的压力会越来越大,一些默认参数已经不能满足集群的日常需求,除此之外,异常的Job在短时间内创建和删除大量文件,引起NN节点频繁更新内存的数据结构从而导致RPC的处理时间变长,CallQueue里面的RpcCall堆积,甚至严重的情况下打满CallQueue,导致NameNode响应变慢,甚至无响应,ZKFC的HealthMonitor监控自己的NN异常时,则会断开与ZooKeeper的链接,从而释放锁,另外一个NN上的ZKFC进行抢锁进行Standby到Active状态的切换。这是一般引起的切换的流程。

当然,如果你是手动去切换这也是可以的,当Active主机出现异常时,有时候则需要在必要的时间内进行切换。

ZKFC的作用是什么?如何判断一个NN是否健康

在正常的情况下,ZKFC的HealthMonitor主要是监控NameNode主机上的磁盘还是否可用(空间),我们都知道,NameNode负责维护集群上的元数据信息,当磁盘不可用的时候,NN就该进行切换了。

 /**
   * Return true if disk space is available on at least one of the configured * redundant volumes, and all of the configured required volumes. * * @return True if the configured amount of disk space is available on at * least one redundant volume and all of the required volumes, false * otherwise. */ public boolean hasAvailableDiskSpace() {  return NameNodeResourcePolicy.areResourcesAvailable(volumes.values(), minimumRedundantVolumes); } 注: minimumRedundantVolumes获取值的方法如下:
minimumRedundantVolumes = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_CHECKED_VOLUMES_MINIMUM_KEY,
        DFSConfigKeys.DFS_NAMENODE_CHECKED_VOLUMES_MINIMUM_DEFAULT);

其中,

 

DFS_NAMENODE_CHECKED_VOLUMES_MINIMUM_KEY = "dfs.namenode.resource.checked.volumes.minimum";
DFS_NAMENODE_CHECKED_VOLUMES_MINIMUM_DEFAULT = 1;

 volumes 获取自 配置项dfs.namenode.shared.edits.dir的值

 

除了可用状态(SERVICE_HEALTHY)之外,还有SERVICE_UNHEALTHY(磁盘空间不可用),SERVICE_NOT_RESPONDING(其他的一些情况)状态,在这两个状态中,它都认为NN是不健康的。

NameNode HA是如何实现的?

我们前面说到,ZKFC是如何判断NN是否健康,接下来当NN处于非健康状态时,NameNode是如何进行切换的呢?

在ZKFailoverController这个类中,实行了两个重要的Callbacks函数,一个叫ElectorCallbacks,另一个叫HealthCallbacks,顾名思义就是选举和健康检查用的回调函数,其中还有两个重要的组成部分elector(ActiveStandbyElector)healthMonitor(HealthMonitor),总体的就如上图所示。

ElectorCallbacks:

/**
   * Callbacks from elector
   */
  class ElectorCallbacks implements ActiveStandbyElectorCallback { @Override public void becomeActive() throws ServiceFailedException { ZKFailoverController.this.becomeActive(); } @Override public void becomeStandby() { ZKFailoverController.this.becomeStandby(); } ... } 

HealthCallbacks:

 /**
   * Callbacks from HealthMonitor
   */
  class HealthCallbacks implements HealthMonitor.Callback { @Override public void enteredState(HealthMonitor.State newState) { setLastHealthState(newState); recheckElectability(); } } 

对于HealthMonitor来说,在ZKFC进程启动的时候,就已经将HealthCallbacks注册进去了,HealthMonitor都会定期的检查NameNode是否健康,我们可以通过监控ha.health-monitor.check-interval.ms去设置监控的间隔时间和通过参数ha.health-monitor.rpc-timeout.ms设置timeout时间,当集群变大的时候,需要适当的设置改值,让ZKFC的HealthMonitor没那么“敏感”

ZKFC通过RPC调用监控NN进程,当出现异常时,则进入不同的处理逻辑,以下是简化的代码:

 private void doHealthChecks() throws InterruptedException { while (shouldRun) { try { status = proxy.getServiceStatus(); proxy.monitorHealth(); healthy = true; } catch (HealthCheckFailedException e) { ... enterState(State.SERVICE_UNHEALTHY); } catch (Throwable t) { ... enterState(State.SERVICE_NOT_RESPONDING); Thread.sleep(sleepAfterDisconnectMillis); return; } ... } 

回调函数就是这么起作用啦,那么回调函数做了什么呢?总的来说,如果NN健康(SERVICE_HEALTHY)就加入选举,如果不健康就退出选举(SERVICE_UNHEALTHYSERVICE_NOT_RESPONDING

 case SERVICE_UNHEALTHY:
        case SERVICE_NOT_RESPONDING:
          LOG.info("Quitting master election for " + localTarget + " and marking that fencing is necessary"); elector.quitElection(true); break; 

说到退出选举就关系到elector(ActiveStandbyElector)了,true代表如果NN从Actice变为Standby出现异常是要去fence的,这就是为啥NN会挂掉的原因之一

如何退出选举?就是close zkClient的链接,让ZooKeeper上面的维持的选举锁消失

void terminateConnection() {
    if (zkClient == null) { return; } LOG.debug("Terminating ZK connection for " + this); ZooKeeper tempZk = zkClient; ... try { tempZk.close(); } catch(InterruptedException e) { LOG.warn(e); } ... } 

对于ActiveStandbyElector来说,他有个WatcherWithClientRef类专门用来监听ZooKeeper上的的znode的事件变化,当事件变化时,就会调用ActiveStandbyElector的processWatchEvent的方法

watcher = new WatcherWithClientRef();
ZooKeeper zk = new ZooKeeper(zkHostPort, zkSessionTimeout, watcher);

/**
   * Watcher implementation which keeps a reference around to the
   * original ZK connection, and passes it back along with any
   * events.
   */
  private final class WatcherWithClientRef implements Watcher { ... @Override public void process(WatchedEvent event) { hasReceivedEvent.countDown(); try { hasSetZooKeeper.await(zkSessionTimeout, TimeUnit.MILLISECONDS); ActiveStandbyElector.this.processWatchEvent( zk, event); } catch (Throwable t) { fatalError( "Failed to process watcher event " + event + ": " + StringUtils.stringifyException(t)); } } ... } 

在ActiveStandbyElector的processWatchEvent方法中,处理来自不同事件的逻辑重新加入选举或者继续监控znode的变化,当另外一个ZKFC监控到事件变化得时候,就去抢锁,抢锁实质上就是创建znode的过程,而且创建的是CreateMode.EPHEMERAL类型的,所以,当HealthMonitor监控到NN不健康时,就会断开连接,节点就会消失,watcher就会监控到NodeDeleted事件,进行创建节点。

 switch (eventType) {
      case NodeDeleted:
        if (state == State.ACTIVE) {
          enterNeutralMode();
        }
        joinElectionInternal();
        break;
      case NodeDataChanged: monitorActiveStatus(); break; 

又因为ActiveStandbyElector实现了StatCallback接口,当节点创建成功时,就会回调processResult方法看是否创建成功,如果创建成功则去检查zkBreadCrumbPath是否存在之前的Active节点,如果存在,则调用RPC让其变为Standby,看能否转变成功,否则则SSH过去fence掉NN进程。,保持Active节点只有一个,并且恢复正常服务

NameNode因为断电导致不能切换的原理,怎样进行恢复

ActiveNN断电,网络异常,负载过高或者机器出现异常无法连接,Standby NN无法转化为Active,使得HA集群无法对外服务,原因是Active NN节点在断电和不能服务的情况下,zknode上保存着ActiveBreadCrumb, ActiveStandbyElectorLock两个Active NN的信息,ActiveStandbyElectorLock由于Active NN出现异常断开,Standby NN去抢锁的时候就会去检查ActiveBreadCrumb是否有上一次的Active NN节点,如果有,就会就会尝试让Active NN变为Standby NN,自己转化为Active NN,但是由于调用出现异常,所以会采用ssh的方式去Fence之前的Active NN,因为机器始终连接不上,所以无法确保old active NN变为Standby NN,自己也无法变为Active NN,所以还是保持Standby状态,避免出现脑裂问题。

解决方案是确定Active关机的情况下重新hdfs zkfc -formatZK就可以了。

总 结

NN GC或者在压力大的情况下可以调整GC算法和增加NameNode节点的线程数,加快NN对请求的处理速度,也可以分离节点的端口dfs.namenode.rpc-address.ns1.nn2dfs.namenode.servicerpc-address.ns1.nn2分离client和datanode节点等服务类型的请求,进行分担压力,也可以适当的调整ZKFC的监控timeout的时间等等

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
分布式计算 NoSQL Hadoop
DataNode 如何向 NameNode 发送心跳的
心跳是分布式技术的常用手段,而 DataNode 和 NameNode 维持心跳的过程,在我们自己开发的分布式系统中,很有借鉴意义
|
3月前
|
运维 分布式计算 监控
NameNode如何处理DataNode故障?
【8月更文挑战第31天】
155 1
|
3月前
|
分布式计算 安全 Hadoop
HDFS NAMENODE 安全模式
HDFS NAMENODE 安全模式
|
3月前
|
存储 分布式计算 Hadoop
|
4月前
|
分布式计算 Hadoop
Hadoop中NameNode故障
【7月更文挑战第11天】
70 3
|
5月前
|
存储 分布式计算 监控
Hadoop集群添加新的DataNode
【6月更文挑战第19天】
197 1
|
6月前
|
存储 分布式计算 Hadoop
NameNode和DataNode在HDFS中的作用是什么?
NameNode和DataNode在HDFS中的作用是什么?
393 0
|
存储 分布式计算 Hadoop
HDFS Namenode挂掉后分析解决
HDFS Namenode挂掉后分析解决
270 1
|
机器学习/深度学习 缓存 分布式计算
Hadoop基础学习---4、HDFS写、读数据流程、NameNode和SecondaryNameNode、DataNode
Hadoop基础学习---4、HDFS写、读数据流程、NameNode和SecondaryNameNode、DataNode
|
分布式计算 Hadoop
hadoop 的 namenode 宕机,怎么解决?
hadoop 的 namenode 宕机,怎么解决?
360 0