原文出自云台博客:http://yuntai.1kapp.com/?p=935
在NameNode接受数据块报告的过程中,会检查块的副本中是否有无效块,坏块,无效块,和块的副本数不够问题,由于这部分涉及到NameNode对块管理的核心机制,在这里独立出来进行分析。
无效块:如果DN报告上来了块信息,但是该块副本信息在NN端找不到,认为该块为无效,加入无效集合invalidateBlocks进行处理,该状态的块副本最终会在ReplicationMonitor线程中进行处理。因为该块副本在NN中没有记录,因此不用在NN内存内处理与DN关系,和从blocks中将其删除操作;
4.3.1.坏块处理
在处理块报告的环节中,对于坏块的处理,首先会检查所有报告上来的块副本是否损害,然后再对计算获得的坏块进行处理,首先分析检查块副本是否损坏
4.3.1.1.坏块检查
坏块检查,主要是在报告上来的块状态与NameNode记录的该块状态情况下,对报告上来块的时间戳,及其块的长度与NameNode记录的值进行比较,如果有某项不一致,就认为该块损坏了,加入损坏列表。
DN报告状态 | FINALIZED | RBW | RWR | RUR | TEMPORARY |
NN记录状态 | COMPLETE | UNDER_RECOVERY |
|
当DN报告的块状态为FINALIZED时,NN记录该块状态为COMPLETE,COMMITTED时,检查该副本时间戳与块长度是否与NN记录的一致,不一致,则说明该块被损坏了,需要将该块加入损坏列表,准备处理,NN上记录的块副本状态为其他状态,不认为该块副本损坏,比如块为UNDER_CONSTRUCTION状态,本来该块就还在构建过程中,不应该为损坏;
当DN报告的块状态为RBW,RWR时,可能在数据块管道传输数据流时出现异常,某DN节点仅接受了部分块信息,这类型块报告给NN,当然时间戳与块长度是否与NN记录的不会一致,则写块也会认为损坏了。
当DN报告的块状态为RUR,TEMPORARY时,则认为该副本损坏,因为正常情况下,则两个状态不应该被报告。
4.3.1.2.坏块处理
在上一个环节中,已经收集好坏块副本信息,本节将会对这些块进行处理。首先将块副本所在的DN节点加入有副本损坏的DN集合(可以通过损坏的block信息找到该集合),然后计算该副本所对应块的所有副本状态并统计副本,如果有效副本大于冗余因子,会考虑将该块副本加入无效集合。在该阶段,首先将该副本加入无效集合invalidateBlocks,然后会解除DN节点与副本的关系(如果块本来对于了3个DN节点,现在则只对应2个),同时也会将该副本从blocks中删除(如果该块副本数为0,或者不属于任何一个文件),同时也会检查excessReplicateMap集合中是否有该副本,因为既然该副本已经加入了invalidateBlocks集合,就不用存在excessReplicateMap中,否则可能会出现二次删除,抛出异常。
注:上面提到的集合blocks,该集合存储了HDFS集群所有的块(即冗余因子为1的情况下块的数目),如果集合存储的数据量很大,这该集合存储的信息就会很大,该集合在HDFS内重新实现,而没有直接使用Java本身提供集合。也是考虑到存储和操作的数据集合会特别巨大,后面会详细对这些重构集合进行深入分析。
4.3.2.添加块映射
当DN报告块副本到NameNode后,NameNode经过一系列坏块,无效块,块映射还未建立后,开始准备建立副本与DN之间的映射,以便在读取文件的时候,能够获取到该副本。具体流程如下:
1、 再次判断该块是否为UC状态,如果是UC状态,再次从blocksMap中查询块副本是否为UC,因为可能由于另外一个线程已经该副本转换为完成状态;
2、 建立副本与DN映射关系;
3、 检查块状态是否为COMMITTED,且该块副本数量大于最小副本数量,如果为真,设置该块状态为完成状态(COMPLETE);
4、 检查该副本对应的块是否仍然需要冗余,不过不需要,将该块从neededReplications中删除,如果副本数不够,需要将块加入neededReplications集合,在加入该集合的时候,需要提醒的是,会安装该块有效副本情况,来选择不同的优先级加入集合,优先级不同,在处理的时候,先后顺序就不同,意味着可能冗余分数更少的会优先进行冗余,加入过程由UnderReplicatedBlocks类的update方法完成;
5、 如果冗余数过多,会将一些副本加入excessReplicateMap与invalidateBlocks集合;
6、 如果该块仍有损坏的副本,将该副本加入无效集合;
总之,该过程不仅仅建立了块与DN节点的映射,同时也检查了该块副本的状态;