HDFS Maintenance State
来源:互联网 发布:霹雳抢购软件 编辑:程序博客网 时间:2024/06/06 16:25
前言
初一看文章标题,很多人可能比较奇怪“HDFS Maintenance”是什么意思,“HDFS包含”的意思?首先Maintenance这个形似Maintain的单词可不是什么包含的意思,它的解释是维护,维修。那么HDFS Maintenance具体是什么意思呢,HDFS处于维护状态?说起维护状态,我们不禁可以联想到HDFS RollingUpgrad,没错,RollingUpgrade确实与HDFS的维护有点关联。确切地说,HDFS的RollingUpgrade是HDFS Maintenance功能的一个使用场景。下面给大家介绍一下社区目前在开发的这个feature。
HDFS Maintenance的缘来
HDFS Maintenance的提出源自于HDFS Upgrade Domain(升级域)的提出。HDFS升级域是方便于集群做大规模滚动升级之类的操作而提出的HDFS升级域的相关内容可查阅笔者的另外一篇文章:HDFS升级域:Upgrade Domain。在HDFS升级域的讨论与实现过程中,社区提出了DataNode的Maintenance(维护状态)。Maintenance状态是一类新的状态,HDFS现有的状态有以下几种,看完大家可能就知道这是什么意思了。
- Live(In Sevice)
- Decommissioning
- Decommissioned
- Dead
这些状态我们在NameNode的WebUI界面上也能直接看到。那么问题来了,上面4种是否是完美的呢?答案显然不是,如果我们仔细进行分析的话,上面状态的划分不够灵活。在这样的情况下,DataNode不是处于服务状态,就是处于Out of Service状态。而一旦处于Out of Service状态,接下来就会导致replication操作,使集群副本数满足副本系数的要求。所以这里会引出一个问题,我们是否能够定义一个新的状态,使得我们对DataNode的操作能尽可能地对集群没有影响,并能够快速的恢复回去呢?这就是DataNode Maintenance状态的缘由。
DataNode Maintenance状态的定义
与Decommission下线状态类似,Maintenance状态同样有2个细分状态,Enter_Maintenance和In_Maintenance状态。Enter_Maintenance表示的意思是正在进入Maintenance状态。而In_Maintenance表示目前已为Maintenance状态。为什么这里还会有进入Maintenance这样的状态呢?其实大家可以拿Decommission过程与此过程做一个比较。我们在执行下线操作时,为了满足集群副本数的要求,会有一个Decommissioning的状态,此时集群会做replication操作。同理,Enter_Maintenance状态也会做这样的事情,但是它与Decommission过程的目的略有不同。Enter_Maintenance是为了保证集群内有至少满足1个副本以上的数据副本,来保证数据的可用性。比如说当进入Maintenance状态的节点拥有集群中唯一的某块副本时,这时就会做一次replication操作。从一定程度上而言,Maintenance情况下需要满足的最低副本数应比Decommission过程要低,理论上只要存在一个即可。所以如果我们集群都是默认3副本的情况时,那么进入Maintenance状态,基本不会有replication操作了。
如果DataNode处于Maintenance状态了,HDFS对DataNode的节点是怎样处理的呢?主要有以下几点主要影响:
- 集群内不会触发replicate此节点内的块数据。
- DataNode将不接收来自DFSClient端的读写请求。以往DataNode如果处于Out of Service的状态,就会抛出很多的异常。
- DataNode将不会被选为block的存储节点。
- Balancer/Mover操作也将避免移动此节点上的数据。
所以从这里我们可以看到,Maintenance状态的DataNode就是处于一个“维护”的状态,它并不等同于Dead、Decommissioned状态,它能够主动地让NameNode知道自己的状态,并能够随时快速的切换回服务状态。
HDFS Maintenance功能的使用场景
介绍完Maintenance状态的定义之后,我们再来看看它的使用场景。
首先HDFS Maintenance的提出源自于HDFS 升级域的讨论。所以毫无疑问,在滚动升级的过程中,HDFS Maintenance可以起到很大的帮助。这样的话,当每次进行批量rolling upgrade操作的时候,就能够快速进行服务状态的切换,而不用担心操作时间过长导致集群进行replication操作了。
第二个使用场景是DataNode服务的快速切换。在很多情况下,当节点本身出现软件或者硬件层面的问题时,这时我们可能会对其进行临时的停止操作来进行软、硬件的故障恢复操作。这个时候我们就可以使DataNode进入Maintenance状态。在这里,我们可以把DataNode Maintenance理解为DataNode背后的一道开关。
HDFS Maintenance的核心实现
在HDFS-7877上,原作者提交了此功能的patch。笔者对其也进行了学习,给我的感觉是HDFS Maintenance的引入好比在各个操作方法入口上加了一道开关。这里的开关可以具象的理解为if(datanode.inService())的判断。主要在下面几个场景代码中做了处理。
第一处,在调用BlockManager#createLocatedBlock获取块信息的时候做了处理,这步操作会在每次的读请求中被调用。代码改动如下:
private LocatedBlock createLocatedBlock(final BlockInfoContiguous blk, final lon final int numNodes = blocksMap.numNodes(blk); final boolean isCorrupt = numCorruptNodes == numNodes;- final int numMachines = isCorrupt ? numNodes: numNodes - numCorruptNodes;+ int numMachines = isCorrupt ? numNodes: numNodes - numCorruptNodes;+ numMachines -= numberReplicas.inMaintenanceReplicas() ++ numberReplicas.deadEnteringMaintenanceReplicas(); final DatanodeStorageInfo[] machines = new DatanodeStorageInfo[numMachines]; int j = 0; if (numMachines > 0) { for(DatanodeStorageInfo storage : blocksMap.getStorages(blk)) { final DatanodeDescriptor d = storage.getDatanodeDescriptor(); final boolean replicaCorrupt = corruptReplicas.isReplicaCorrupt(blk, d);+ // Don't pick IN_MAINTENANCE or dead ENTERING_MAINTENANCE states.+ if (d.isInMaintenance() || (d.isEnteringMaintenance() && !d.isAlive)) {+ continue;+ }
第二处,在Rereplication过程和普通写请求中的选出目标放置节点的方法过程中,进行了过滤处理,主要集中在下面2个方法。
DatanodeDescriptor chooseSourceDatanode(Block block, corrupt += countableReplica; else if (node.isDecommissionInProgress() || node.isDecommissioned()) decommissioned += countableReplica;+ else if (node.isEnteringMaintenance()) {+ enteringMaintenance += countableReplica;+ if (!node.isAlive) {+ deadEnteringMaintenance += countableReplica;+ }+ } else if (node.isInMaintenance())+ inMaintenance += countableReplica; else if (excessBlocks != null && excessBlocks.contains(block)) { excess += countableReplica; } else {@@ -1638,7 +1682,7 @@ else if (excessBlocks != null && excessBlocks.contains(block)) { if ((nodesCorrupt != null) && nodesCorrupt.contains(node)) continue; if(priority != UnderReplicatedBlocks.QUEUE_HIGHEST_PRIORITY - && !node.isDecommissionInProgress() + && !node.isDecommissionInProgress() && !node.isEnteringMaintenance() && node.getNumberOfBlocksToBeReplicated() >= maxReplicationStreams) {
下面是选择副本放置位置的时候,做了目标存储节点类别的判断。
@@ -764,9 +764,9 @@ private boolean isGoodTarget(DatanodeStorageInfo storage, } DatanodeDescriptor node = storage.getDatanodeDescriptor();- // check if the node is (being) decommissioned- if (node.isDecommissionInProgress() || node.isDecommissioned()) {- logNodeIsNotChosen(storage, "the node is (being) decommissioned ");+ // check if the node is in service+ if (!node.isInService()) {+ logNodeIsNotChosen(storage, "the node isn't in service"); return false; }
第三处,Balancer/Mover操作的时候,需要过滤掉处于Maintenance状态的节点。
由于Balancer/Mover工具在运行的时候,都会调用Dispatcher init方法来执行初始化节点的操作,来过滤掉exclude,decommissioned这类的节点。所以我们在这里只需多加一类判断即可。
首先是Dispatcher的init初始化方法。
/** Get live datanode storage reports and then build the network topology. */ public List<DatanodeStorageReport> init() throws IOException { final DatanodeStorageReport[] reports = nnc.getLiveDatanodeStorageReport(); final List<DatanodeStorageReport> trimmed = new ArrayList<DatanodeStorageReport>(); // create network topology and classify utilization collections: // over-utilized, above-average, below-average and under-utilized. for (DatanodeStorageReport r : DFSUtil.shuffle(reports)) { final DatanodeInfo datanode = r.getDatanodeInfo(); // 此处判断节点是否需要过滤 if (shouldIgnore(datanode)) { continue; } trimmed.add(r); cluster.add(datanode); } return trimmed; }
然后我们进入shouldIgnore方法。
private boolean shouldIgnore(DatanodeInfo dn) { final boolean decommissioned = dn.isDecommissioned(); // ignore decommissioning nodes final boolean decommissioning = dn.isDecommissionInProgress();+ // ignore nodes in maintenance+ final boolean inMaintenance = dn.isInMaintenance();+ // ignore nodes entering maintenance+ final boolean enteringMaintenance = dn.isEnteringMaintenance(); // ignore nodes in exclude list final boolean excluded = Util.isExcluded(excludedNodes, dn); // ignore nodes not in the include list (if include list is not empty) final boolean notIncluded = !Util.isIncluded(includedNodes, dn);- if (decommissioned || decommissioning || excluded || notIncluded) {+ if (decommissioned || decommissioning || excluded || notIncluded ||+ inMaintenance || enteringMaintenance) { if (LOG.isTraceEnabled()) { LOG.trace("Excluding datanode " + dn + ": " + decommissioned + ", "- + decommissioning + ", " + excluded + ", " + notIncluded);+ + decommissioning + ", " + excluded + ", " + notIncluded + ", "+ + inMaintenance + ", " + enteringMaintenance); } return true; }
从以上3处的处理我们可以看到,Maintenance状态的处理与原有的Decommission状态的处理极为相似。当然上述只是笔者简单分析了几处,更多的实现还是建议读者自行阅读原patch代码,上面还有Enter_Maintenance状态时进行最小副本数的判断逻辑。
HDFS Maintenance状态转化图
DataNode Maintenance状态同样支持多种状态之间的转换,下面是原设计中的状态转化图。
HDFS Maintenance状态转换图
本文的内容就是如此,希望大家读完后有所收获。HDFS Maintenance功能预计发布在Hadoop 2.9.0的版本中,目前还在开发中。笔者目前也在关注这个Feature,希望也能贡献自己的一份力吧。
参考资料
[1].https://issues.apache.org/jira/browse/HDFS-7877
[2].https://issues.apache.org/jira/secure/attachment/12709388/Supportmaintenancestatefordatanodes-2.pdf
[3].https://issues.apache.org/jira/secure/attachment/12709387/HDFS-7877-2.patch
- HDFS Maintenance State
- HDFS daily maintenance,, useful command
- maintenance
- Median Maintenance
- State
- state
- State
- state
- State
- state
- STATE
- State
- state
- state
- state
- state
- [问题记录]hadoop/hdfs/name is in an inconsistent state: storage directory(hadoop/hdfs/data/) does not ex
- Software Aging and Maintenance
- Note 7 燃损祸起电池三星将加强安全检查措施
- 算法竞赛入门经典第四章
- nyoj7街区最短路径问题
- python读取excel文件
- Python-命名空间
- HDFS Maintenance State
- 玩转树莓派之经验积累
- 计算球的体积
- Rust : 读含有中文字符的CSV文件解决方案
- 15 个 Android 通用流行框架大全
- c# response.write()输出之后怎么换行
- 4. NVIC中断向量配置—基于CT117E开发板的STM32库函数编程
- ndroid数据库框架——GreenDao轻量级的对象关系映射框架,永久告别sqlite
- SQLyog 导入数据库