NameNode是HDFS的主节点,管理文件系统的命名空间(namespace),命名空间包括文件系统目录树、文件/目录信息以及文件的数据块索引。
其中文件的数据块索引指的是每个文件对应的数据块列表,这个信息保存在INodeFile.blocks字段中。
数据块与数据节点的对应关系,指的是数据块副本保存在哪些数据节点上。这个信息是由DataNode启动时,由DataNode上报给NameNode的,也就是说这部分信息是NameNode动态构建起来的,而不是从fsimage加载的。
注意:
第一关系:文件系统目录树
第二关系:数据块与数据节点的对应关系
INodeFile.blocks字段记录了一个HDFS文件拥有的所有数据块,通过这个字段HDFS第一关系与第二关系发生了关联。
INodeFile.blocks字段是一个BlockInfo类型的数组,BlockInfo类是Block的子类。
1、Block类:
Block类用来唯一标识NameNode中的数据块,是HDFS数据块最基本的抽象接口。Block类定义了三个字段:
①blockId唯一的标识这个Block对象;
②numBytes是这个数据块的大小(单位是字节);
③generationStamp是这个数据块的时间戳;
2、BlockInfo类:
BlockInfo类继承自Block类,是Block类的补充说明。BlockInfo类定义了bc字段保存保存该数据块属于哪一个HDFS文件;triplets字段保存了这个Block的副本存储在哪些数据节点上。
private BlockCollection bc;
private LinkedElement nextLinkedElement;
private Object[] triplets;
3、BlockInfoUnderConstruction类:
HDFS在加载fsimage时,如果当前加载的文件处于正在构建状态,也就是INodeFile中包含FileUnderConstructionFeature特性,则将该INodeFile的最后一个数据块设置为BlockInfoUnderConstruction,表名最后一个数据块正在构建。需要注意的是,处于构建状态的INodeFile除最后一个数据块为BlockInfoUnderConstruction外,其他均为正常的BlockInfo。
当DataNode汇报当前数据块对应的构建中副本状态为FINALIZED,并且当前数据块的状态为COMMITTD,且数据块副本大于等于最小副本数目,NameNode会将当前数据块由BlockInfoUnderConstruction状态转变为BlockInfo,并将数据块状态设置为COMPLETE。
4、BlocksMap类:
BlocksMap管理着NameNode上数据块的元数据,包括当前数据块属于哪个HDFS文件,以及当前数据块保存在哪些DataNode上。当DataNode启动时,会对DataNode本地磁盘进行扫描,并将当前DataNode上保存的数据块信息汇报到NameNode。NameNode收到DataNode汇报信息后,会建立数据块与保存这个数据块的数据节点的对应关系,将这些信息保存在BlocksMap中。
private final int capacity = LightWeightGSet.computeCapacity(2.0D, "BlocksMap");
private GSet<Block, BlocksMap.BlockInfo> blocks;
5、Replica类:
数据块:NameNode中的数据块信息
副本:DataNode中保存的数据块
HDFS源码中使用Replica对象描述副本:
public static enum ReplicaState {
FINALIZED(0),
RBW(1),
RWR(2),
RUR(3),
TEMPORARY(4);
}
FINALIZED:DataNode上的副本已经完成写操作,不再修改。
RBW(ReplicaBeingWritten):刚刚被创建或者追加写的副本,处于写操作的数据流管道中,正在被写入。
RUR(ReplicaUnderRecovery):数据块恢复时所处的状态。
RWR(ReplicaWaitingToBeRecovered):如果一个DataNode挂掉并且重启之后,所有RBW状态的副本都将转换为RWR状态。RWR状态的副本不会出现在数据流管道中,等着进行租约恢复操作。
TEMPORARY(ReplicaInPipeline):DataNode之间传输副本时,正在传输的副本就处于TEMPORARY状态。与RBW状态的副本不同的是,TEMPORARY状态的副本内容是不可读的,如果DataNode重启,会直接删除处于TEMPORARY状态的副本。
6、Block类状态:
public static enum BlockUCState {
COMPLETE,
UNDER_CONSTRUCTION,
UNDER_RECOVERY,
COMMITTED;
private BlockUCState() {
}
}
complete:数据块的长度和时间戳不再发生变化,并且NameNode已经收到至少一个DataNode报告有FINALIZED状态的副本。一个COMPLETE状态的数据块会在NameNode的内存中保存所有FINALIZED副本的位置。
under_construction:文件被创建挥着进行追加写操作时,正在被写入的数据块就处于under_construction状态。
under_recovery:正在进行租约恢复和数据块恢复流程的数据块处于under_recovery状态。
committed:处于committed状态的数据块表明客户端已经把该数据块的所有数据都发送到了DataNode组成的数据流管道中,但是NameNode还没有收到任何一个DataNode汇报有finalized副本。