一、文件系统目录树与FSDirectory类

最近在研究HDFS源码,个人感觉很难,头发都快要掉光了O__O "…

一、文件系统目录树 (HDFS第一关系)

HDFS的目录和文件在内存中是以一棵树的形式存储的,这个目录树是由NameNode维护的,NameNode会修改这个树形结构以对外提供添加、删除文件等操作。文件系统目录树还保存着HDFS文件与数据块的对应关系。

不管是文件还是目录,在文件系统目录树中都被看作是一个INode节点。如果是目录,则其对应的类是INodeDirectory;如果是文件,则其对应的类是INodeFile。INodeDirectory中包含一个成员集合变量children,如果该目录下有子目录或者文件,其子目录或文件的INode引用就会被保存在children集合中。HDFS通过这种方式维护整个文件系统的目录结构。

INode是抽象类,保存了HDFS目录和文件的所有共同属性,包括当前节点的父节点的INode对象的引用、文件、目录名、用户组、访问权限等。需要注意的是,INode类的设计采用了模板模式。INode类定义的方法多为2个,一个是final的接口方法,用于规范接口的调用;另一个是abstract抽象方法,抽象方法留给子类具体实现。INode类中只有一个字段,就是parent,表名当前INode的父目录。

INodeWithAdditionalFields类定义了id、name、permission等字段,并覆盖了INode抽象方法。其中permission字段是64位的long类型的,保存用户信息、用户组信息和权限信息。HDFS中用户名和用户标识的对应关系、用户组名和用户组标识的对应关系都保存在SerialNumberManager类中,通过SerialNumberManager类,名字节点不需要在INode对象中保存字符串形式的用户名和用户组名,只需将整形的用户名标识和用户组名标识放入permission字段即可。这种设计节省了INode对象对内存的占用。

INodeDirectory:抽象了HDFS文件系统中的目录,主要分为几类方法:

children字段的增删改查:用于向当前目录添加、删除、替换、查找子目录等操作,包括:addChild()、removeChild()等方法;

特性(Feature)相关方法:用于向当前INodeDirectory添加新的Feature对象以及获取指定Feature对象的方法;

快照相关方法:向当前目录添加、删除或者更改快照等操作。

INodeFile类:抽象了一个HDFS文件,继承自INodeWithAdditionalFields。

INodeFile类中保存了HDFS文件的文件头header字段和文件对应的数据块信息blocks字段。

header字段保存了当前文件有多少个副本以及文件数据块的大小;

blocks字段是一个BlockInfo类型的数组,BlockInfo类继承自Block类,它保存了数据块与文件、数据块与数据节点的对应关系。从BlockInfo对象可以获得数据块所属的文件,及文件的INodeFile对象,也可以获得保存数据块副本的所有数据节点的信息。

有以下几类方法:

构建特性相关方法:当HDFS客户端写文件时,该文件就处于构建状态。通过在INodeFile中添加FileUnderConstructionFeature特性表示文件处于构建状态。

快照特性相关方法:对处于快照中的文件进行修改时,HDFS首先想这个文件中添加FileWithSnapshotFeature特性,表名这个文件在快照中。

二、FSDirectory类:

HDFS文件系统的命名空间(namespace),也就是以“/”为根的整个目录树,是通过FSDirectory类来管理的。需要注意的是,FSNamesystem也提供了管理目录树结构的方法,但是FSNamesystem中的方法多是调用FSDirectory类来实现的,FSNamesystem在FSDirectory类方法的基础上添加了editlog日志记录功能。而FSDirectory的操作全部是在内存中进行的,并不进行editlog的日志记录。

为何引入FSDirectory类?

引入FSDirectory类,是想要将文件系统目录树的所有操作抽象成一个统一的接口,这样其他子系统在调用目录树操作时就不需要了解目录树内部实现的复杂逻辑了,只需调用FSDirectory对象上的指定方法就可以了。而FSDirectory知晓如何将这些目录树的操作分派到具体实现的各个对象上,并实现对应的逻辑。FSDirectory的设计采用门面(Facade)模式,降低了其他HDFS逻辑与目录树逻辑的耦合性。

主要成员变量有:

rootDir:整个文件系统目录树的根节点,是INodeDirectory类型的;

namesystem:NameNode门面类,这个类主要支持对数据块进行操作的一些方法,如addBlock();

inodeMap():记录根目录下所有的INode,并维护INodeId->INode的映射关系;

dirLock:对目录树以及inodeMap字段操作的锁;

nameCache:将常用的name缓存起来,以降低byte[]的使用,并降低Java堆的使用;

FSDirectory类主要是封装了对文件系统目录树的操作,如增删改查。

几个典型方法:

addChild():向文件系统目录树的某个目录节点添加一个child子节点;

addBlock():在指定的INode节点上添加一个数据块,它通过namesystem获取BlockManager对象,并在BlockManager对象上调用addBlockCollection()方法将一个Block添加到BlockManager的blockMap字段中保存,之后调用INodeFile.addBlock()方法将Block对象添加到INode对象的blocks字段中保存。

 

 

 

你可能感兴趣的:(HDFS源码)