其实我很害怕阅读源代码,不过得克服自己的恐惧感,所以打算开始阅读HDFS的源码,学习它主要有需要两个方法配合使用一是阅读源码,找到入口函数,然后根据一步步的跳转和关键数据结构的学习来了解 二是运行源码,然后设置断点跟踪执行流程,比如说client端发出ls 命令,然后跟踪此命令执行过程都调用了哪些函数,执行了什么任务,就一目了然了。

HDFS的框架结构,在上一篇日志中已经给出来了,这里就不再重复了。

从框架可以看出,HDFS中主要由namenode和datanode来组成,namenode只有一个,属于人类的大脑级任务,一旦namenode崩溃系统也就崩溃了,虽然有second namenode,但是瓶颈依然在这里。namenode的主要功能有两个一个是扮演着namespace管理者的角色,另外一个则是hDFS的inode table,管理着block的映射。

1)  filename->blocksequence (namespace)  此表存储在磁盘上,在namenode启动的时候会加载,是非常重要的资源
2)  block->machinelist ("inodes")  此表是在namenode启动后由datanode向namenode上报block信息之后创建起来的。

nn(namenode)提供的是始终被动接收服务的server,主要有协议接口:ClientProtocol接口、DatanodeProtocol接口、NamenodeProtocol接口,RefreshAuthorizationPolicyProtocol接口,RefreshUserMappingsProtocol接口。DataNode(简称dn)主要是用来存储数据文件,hdfs将一个文件分割成一个个的block,这些block可能存储在一个DataNode上或者是多个DataNode上。dn负责实际的底层的文件的读写,如果客户端client程序发起了读hdfs上的文件的命令,那么首先将这些文件分成block,然后nn将告知client这些block数据是存储在那些dn上的,之后,client将直接和dn交互。

nn主要是作为namenode server的角色来执行操作的,大部分的文件操作都转交给FSNamesystem的类来完成,而nn本身则关注于IPC接口,Http Server接口以及一些配置管理操作。

上面的类图结构中仅列出了部分重要的数据结构,查看源码可以了解到以上的每个类文件都很长,也有很多的数据变量,分别应用到各个方面。

<一> FSDirectory

FSDirectory存储整个HDFS的目录状态,通过调用FSImage和FSEditLog的方法从namenode本地磁盘读取元数据信息和向本地磁盘写入元数据信息,并将目录结构所作的修改写入到日志文件中。另外,FSDirectory保存了<filename, blocks>的映射关系。

INode 基类表示文件文件系统中的一个文件或者文件目录的抽象

INodeDirectory表示文件系统中的目录节点

INodeDirectory的关键数据结构是List<INode> children记录了目录下所有的子节点信息

INodeDirectoryWithQuota表示有配额限制的目录,根目录就是这种类型(存储在FSDiretory中)

INodeFile表示文件系统中一个文件节点

INodeFile类中最重要的数据结构是BlockInfo blocks[],它记录了一个文件所包含的所有Block,成员方法的操作大都与Block相关

INodefileUnderConstruction表示正在构建的文件



<二> FSImage

FSImage持久化着文件和目录的元数据信息,每次namenode启动时都从磁盘将FSImage加载到内存中构建目录结构树,之后的操作都存储在editLog中,系统会定期的将editLog中的操作与FSImage进行刷新合并,从而保存最新的FSImage。

fsimage是一个二进制文件,当中记录了HDFS中所有文件和目录的元数据信息,格式如下,这是网上流传的一张经典图,这是淘宝的一个师兄画的:

imageVersion(int)——image版本号

namespaceID(int)——命名空间ID,在namenode的生命期内保持不变,datanode注册时返回作为其registrationID,每次和namenode通信时都要检查,不认识的namespaceID拒绝连接.

numFiles(16版以后long型)记录文件系统中的文件数

genstamp(long)生成image时间戳

下面是numFiles个文件(目录)信息:

path(String)——文件或目录路径

replication(int)——副本数,会调用FSEditLog.adjustReplication(replication);调整,目录的为0

mtime(long)——修改时间

atime(long)——访问时间

blockSize(long)——块大小,目录是0

NumBlocks(int)——文件包含的块数(imageVersion 9以后的版本numBlocks>=0时表示文件,之前的版本>0时表示文件),目录的为-1,saveINode2Image方法中可以看到

如果是文件,下面是NumBlocks个block的相关信息:

blockId(long)——该文件的block的blockid,

numBytes(long)——该block的大小

generationStamp(long)——该block的时间戳

如果是目录,读入quota信息:

nsQuota(long)命名空间大小配额,默认-1

dsQuota(long)磁盘空间配额,默认-1

下面是权限相关

username(String)文件或目录的所属用户名

groupname(String)组名

permission(short)权限

如果前面的path.length==0,表示根目录,设置根目录的配额,修改时间,访问时间和权限信息。

将这些信息读入内存之后,构造一个文件目录结构树,将表示文件或目录的节点填入到结构中。

再之后是加载FilesUnderConstruction.

今天就写到这里吧 果然看代码还是挺累 挺慢的