前言
在HDFS中,每时每刻都在进行着大量block块的创建和删除操作,这些庞大的block块构建起了这套复杂的分布式系统.普通block的读写删除操作一般人都或多或少了解过一些,但是过量的副本清理机制是否有人知道呢,就是overReplicatedBlock的处理,针对过量的副本块,HDFS怎么处理,何时处理,处理的策略机制如何,本文就给大家分享HDFS在这方面的知识.
过量副本块以及发生的场景
过量副本块的意思通俗解释就是集群中有A副本3个,满足标准的3副本策略,但是此时发生了某种场景后,A副本块突然变为5个了,为了达到副本块的标准系数3个,系统就会进行多余2块副本的清除动作,而这个清除动作就是本文所要重点描述的.过量副本块的现象是比较好解释的,那么问题来了,到底有哪些潜在的原因或条件会触发多余副本块的发生呢(在此指的是HDFS中)?本人通过对HDFS源码的阅读,总结出一下3点
ReCommission节点重新上线.这类操作是运维操作引起的.节点下线操作会导致大量此节点的block块在集群中大量拷贝,一旦此节点取消下线,之前已拷贝的大量块必然会成为多余的副本块.
人为重新设置block replication副本数.还是以A副本举例,A副本当前满足标准副本数3个,此时用户张三通过使用hdfs的API方法setReplication人为设置副本数为1.此时也会早A副本数多余2个的情况,即使说HDFS中的副本标准系数还是3个.
新添加的block块记录在系统中被丢失.这种可能相对于前2种case的情况,是内部因素造成.这些新添加的丢失的block块记录会在BlockManager进行再次扫描检测,防止出现过量副本的现象.
OK,以上3种情形就是可能发生过量副本块的原因.至于这3种情况是如何一步步的最终调用到处理多余副本块的过程在后面的描述中会再给出,先来看下多余副本块是如何被选出并处理掉的.
OverReplication多余副本块处理
多余副本块的处理分为2个子过程:
- 多余副本块的选出
- 选出的多余副本块的处理
我们从源码中进行一一寻找原因,首先副本块的选出.
多余副本块的选择
进入blockManager的processOverReplicatedBlock方法,很显然,方法名已经表明了方法操作的本意了.
/**
* Find how many of the containing nodes are "extra", if any.
* If there are any extras, call chooseExcessReplicates() to
* mark them in the excessReplicateMap.
*/
private void processOverReplicatedBlock(final Block block, final short replication, final DatanodeDescriptor addedNode, DatanodeDescriptor delNodeHint) {
此方法的注释的意思是找出存在”多余”的节点,如果他们是多余的,调用chooseExcessReplicates并标记他们,加入加入到excessReplicateMap中.下面进行细节的处理
// 节点列表变量的声明
Collection<DatanodeStorageInfo> nonExcess = new ArrayList<DatanodeStorageInfo>();
// 从corruptReplicas变量中获取是否存在坏的block所在的节点
Collection<DatanodeDescriptor> corruptNodes = corruptReplicas.getNodes(block);
继续后面的处理
// 遍历此过量副本块所在的节点列表
for(DatanodeStorageInfo storage : blocksMap.getStorages(block, State.NORMAL)) {
final DatanodeDescriptor cur = storage.getDatanodeDescriptor();
...
LightWeightLinkedSet<Block> excessBlocks = excessReplicateMap.get(cur
.getDatanodeUuid());
// 如果在当前过量副本图对象excessReplicateMap中不存在
if (excessBlocks == null || !excessBlocks.contains(block)) {
//并且所在节点不是已下线或下线中的节点
if (!cur.isDecommissionInProgress() && !cur.isDecommissioned()) {
// 并且这个副本块不是损坏的副本块
// exclude corrupt replicas
if (corruptNodes == null || !corruptNodes.contains(cur)) {
// 将此过滤副本块的一个所在节点加入候选节点列表中
nonExcess.add(storage);
}
}
}
}
所以从这里看出nonExcess对象其实是一个候选节点的概念,将block副本块所在的节点列表进行多种条件的再判断和剔除.最后就调用到选择最终过量副本块节点的方法
chooseExcessReplicates(nonExcess, block, replication,
addedNode, delNodeHint, blockplacement);
进入chooseExcessReplicates方法
// first form a rack to datanodes map and
// 首先会形成机架对datanode节点的映射关系图
BlockCollection bc = getBlockCollection(b);
final