美文网首页
Hadoop HA 状态转换源码分析

Hadoop HA 状态转换源码分析

作者: 小北觅 | 来源:发表于2020-08-14 16:21 被阅读0次

    今天聊一聊Hadoop HA架构下Namenode的状态转换,也即如下两种转换:
    Active -----> Standby
    Standby ------> Active
    这两种转换分别对应了NameNode类的两个方法:transitionToActive和transitionToStandby

    相关的方法在HAServiceProtocol中定义,最终由NameNodeRpcServer的对应方法相应。我们直接从NameNodeRpcServer类中的方法看起

    一、transitionToStandby

    首先来看由Active -----> Standby

    transitionToStandby方法分成三部分:
    ①检查NN是否已经启动
    ②检查改变NN状态的请求是否是有效的。例如当配置了auto failover后,HAAdmin Cli的非强制转换NN状态请求会被拒绝;如果是来自ZKFC但是没有配置auto failover也会被拒绝。
    ③转换成standby NN

    所以我们主要关注③中的transitionToStandby()方法。点进去:

    这个方法是NameNode类中的一个synchronized方法。首先检查了用户是不是有超级用户的特权,这个我们不用关心。然后判断如果没有启用HA的话,抛出异常。最后也是最重要的是调用了HAState#setState方法把当前的NN状态变成StandBy状态。
    state.setState(haContext, STANDBY_STATE);

    HAState在HA模式下有两个子类。分别是ActiveStateStandbyState,如下图。

    因为我们是从Active->StandBy。所以当前是Active的,所以上面调用的setState方法是ActvieState类中的setState方法。追进去看:

    追到setStateInternal方法中:

    这个方法的主要逻辑是:
    ①做一些退出当前状态的准备工作
    ②进入新状态的准备工作
    ③获取写锁,退出现在的状态,设置新状态,进入新状态,更新最近一次HA状态转换的时间为当前系统时间。释放写锁。

    我们对上面的①②③分别介绍:

    ①做一些退出当前状态的准备工作

    通过层层追踪,最终到这个方法,目的是取消StandBy状态节点上正在进行的checkpoint操作。由于我们现在是Active,所以standbyCheckpointer是null,也就是什么都不做。

    image.png

    ②进入新状态的准备工作
    这个方法在prepareToExitState之后调用,在exitState之前调用。而且需要被子类重写。由于我没有找到有谁重写了这个方法,所以跳过。可能后面的版本会有?

    ③获取写锁,退出现在的状态,设置新状态,进入新状态,更新最近一次HA状态转换的时间为当前系统时间。释放写锁。

    首先是退出当前的状态,这一步会去调用FSNamesystem#stopActiveServices方法来停止一些线程的工作,这个方法是Active,Standby停止服务的通用方法,所以会去判空,比如StandBy节点没有leaseManager等。对于Standby节点则停止editlogRoller等,对于Active节点则停止leasemanager、cacheManager,blockManager等管理类 。重要的一步是更新最后写入Editlog的transaction id。

    接着把HAContext的state设置为StandBy。

    然后准备进入StandBy状态,即调用StandbyState#enterState。最终调用了FSNamesystem#startStandbyServices方法,如下:


    image.png

    这个方法主要做了这些工作:把EditLog状态变成可读,设置blockManager能够把一些块汇报放到延迟处理队列中,取消quota,开启一个editLogTailer用来拉取editlog,开启一个standbyCheckpointer。

    其实到这里就结束了transitionToStandby。接下来挖个坑,后续研究editLogTailer,standbyCheckpointer这两个组件。

    二、transitionToActive

    下面来看Standby ------> Active。看过了从Active->StandBy,就很好理解了,过程很相似(反向操作)。

    不同之处在于从Standby--->Active状态切换ActiveState#enterState调用的方法是FSNamesystem#stopStandbyServices和FSNamesystem#startActiveServices方法,来关闭当前的standby服务并启动成为Active节点所需要的服务。

    首先来看FSNamesystem#stopStandbyServices方法:

    主要工作就是把standbyCheckpointer和editLogTailer停止掉,关闭当前的editlog。

    接下来看FSNamesystem#startActiveServices方法:

    这个方法其实就是和上面的stop对应,把上面关掉的服务启动起来,走进startActiveServices方法看一下:

    代码很长,一点一点来分析。

    首先检查editlog是不是open for write。 如果editlog处在IN_SEGMENT或者BETWEEN_LOG_SEGMENTS状态,则是open for write的。如果不是就进入到if语句中去。

    接着调用FSEditLog#initJournalsForWrite方法,初始化多种JournalManager,并加入到JournalSet中,使FSEditLog状态进入BETWEEN_LOG_SEGMENTS 状态。
    接着对editlog进行恢复操作(也就是要finalize editlog),接着要与之前的Active节点的同步editlog内容,把editlog加载到当前的fsimage中。
    由于要变成Active,所以不再延时处理数据块,所以调用
    blockManager.setPostponeBlocksFromFuture(false);
    把所有datanode设置为stale的,直到收到它们的心跳。清除blockManager中所有的队列,处理之前由于Namespace信息不完整而延迟处理的数据块。读取最新的txid,重置editlog的txid,之后打开editlog。

    剩下的就是启动一些线程:cacheManager、nnEditLogRoller、NameNode资源监控线程、blockManager线程。

    END!

    相关文章

      网友评论

          本文标题:Hadoop HA 状态转换源码分析

          本文链接:https://www.haomeiwen.com/subject/rqmidktx.html