一 Block、Replica、BlocksMap
HDFS使用Block类抽象NameNode中的数据块,Block实现了Writable接口,是可以序列化的,并且实现了Comparable接口,可以按照blockid大小排序。
定义了三个字段:
blockId:唯一标识符
numBytes:数据块大小
generationStamp:这个数据块的时间戳
BlockInfo类扩展自Block,是Block的补充说明,定义了该数据块属于哪一个HDFS文件,定义了triplets保存这个Block副本存储在哪些数据节点上。
BlocksMap: 管理着NameNode上数据块的元数据,包括当前数据块属于哪一个HDFS文件,以及当前数据块保存在哪些DataNode上。
当DataNode启动时,会对DataNode的本地磁盘进行扫描,并将当前DataNode上保存的数据块信息汇报到NameNode.NameNode收到DataNode的汇报,会建立数据块与保存这个数据块的DataNode的对应关系,并将这个信息保存到BlocksMap中。
通过GSet对象维护着Block->BlockInfo的映射关系,GSet是hadoop自己实现的一个比较的特殊的集合类型,特殊点在于他是一个集合,但是却提供了类似映射的功能。
Replica:我们将NameNode的数据块信息叫做数据块,将DataNode上的数据块叫做副本。
Replica的状态:
FINALIZED:DataNode上的副本已完成操作,不再修改。使用FinalizedReplica描述
RBW:刚刚被创建或者追加写的副本,正在被写入,且已经写入的副本的内容还是可读的,使用ReplicaBeingWritten描述
RUR:租约过期之后发生租约恢复和数据块恢复时副本所处的状态。RUR状态的副本使用ReplicaUnderRecovery类描述。
RWR:如果一个DataNode挂掉并重启后,所有RBW状态的副本都将转换RWR状态。RWR状态的副本不会出现在数据流管道中。
TEMPORARY:DataNode之间传输副本时,正在传输的副本就是临时状态。
Block类状态
NameNode中数据块有四种状态:
COMPLETE:数据块的长度和时间戳不再变化,并且NameNode至少收到一个DataNode报告有FINALIZED状态的副本
UNDER_CONSTRUCTION:文件被创建或者进行追加写操作的时候,正在被写入的数据块就处于正在构建状态,长度和时间戳都是可变的
UNDER_RECOVERY:如果一个文件的最后一个
COMMITED:客户端在写文件时的时候,每次请求新的数据块,或者关闭文件时候,都会顺带对上一个数据块进行提交。上一个数据块
UNDER_CONSTRUCTION转化成COMMITED状态
二 数据块副本状态
BlockManager管理和维护着所有与数据块相关的操作,会将不同状态的数据块副本放到不同的数据块副本集合。
损坏的数据块副本集合:CorruptReplicaMap
客户端发现损坏的数据块时,会通过ClientProtocal.reportBadBlocks向NameNode汇报损坏的数据块副本;客户端会通过DataNodeProtocal.
reportBadBlocks方法汇报损坏的数据块副本。之后BlockManager会将损坏的副本加入到CorruptReplicaMap,保存了损坏的数据块副本与保存这个副本的DataNode的对应关系(Block->DataNode)
等待删除的数据块副本集合:InvalidateBlocks
InvalidateBlocks的数据块副本来自于损坏的数据块副本和多余的数据块副本这两个集合。BlockManager的ReplicationMonitor线程会定期执行删除操作,每一次删除的时候,ReplicationMonitor线程都会从
InvalidateBlocks中选出nodeToProcess个DataNode进行删除操作,然后再从每一个DataNode上选出dfs.block.invalidate.limit个副本删除,默认1000.
推迟操作的数据块副本集合:postponedMisreplicatedBlocks
多于的数据块副本集合:excessReplicaMap
等待复制的数据块副本集合:neededReplications