Hadoop HA 状态转换源码分析

今天聊一聊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设置为Active。

然后准备进入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!
毁灭吧,赶紧的,累了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叹了口丶气

觉得有收获就支持一下吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值