HDFS读书笔记-了解NameNode(二)

朋友写的【HDFS系列】,觉得挺好。原文地址,点我

     上篇文章中我们着重介绍了HDFS的基本架构和读写流程,本章主要来认识HDFS的NameNode,
     简单来讲,NameNode就是HDFS的大脑,任何客户端或者DataNode的数据迁移、目录操作都是由NameNode来完成的。
     再了解了NameNode会干什么事情之后,最好深入的办法就是来看NameNode有哪些重要的数据结构,每个数据结构都干什么事情。

 

     我们提到NameNode主要是维护文件在哪里这个映射关系。故而主要包含的内容是:
     1、fileName和目录block的关系。
     2、block到mist(机器列表)的关系。
     fileName到block的关系是fsimage(类似镜像文件)写入到本地,每次启动的时候进行加载。block到mlist的的关系则是通过HDFS启动后,DataNode向NameNode报告心跳实现。为什么这样设计的原因:
     1、文件和目录block的关系存在的时候不会发生变化。
     2、block和mlist的关系会因为均衡数据迁移,机器故障数据迁移发生变化。
     3、架构考虑点。
    NameNode只有三种交互。
     1、client访问NameNode获取相关DataNode信息。
     2、DataNode心跳汇报当前block情况。
     3、SecondaryNameNode做checkpoint交互。
先来看类图:
HDFS读书笔记-了解NameNode(二)

FSNameSystem
    在NameNode中,基本上重要的创建,维护,同步,更新都操作都是通过FSNameSystem来完成的。各种关键的数据结构也是在FSNameSystem中维护的。可以这样说基本上做的所有操作都是通过和FSNameSystem打交道来完成的。

FSDirectory
    顾名思义,该类是用来维护所有以文件路径的。这个类维护着HDFS中所有的目录信息,并且会被持久化到NameNode本地作为FSImage(非常紧凑的二进制文件)存储起来。FSImage的相关操作也是通过FSDirectory完成的,HDFS的各种操作,会记录到EditLog中(EditLog也是通过FSDriectory维护),周期性的把FSImage和EditLog合并起来就是当前所有的目录信息。
HDFS所有的目录信息是通过树的方式来维护的。(想象一下普通的电脑上的文件不都是以树的方式维护的吗),在HDFS中所有文件的抽象是INode,目录则是INodeDirectory,文件则是INodeFile。

FSImage
    从上一部分我们已经了解到了,FSImage就是文件目录元数据的某个时间段的镜像文件。每次启动后所有文件目录操作都会通过FSDriectory记录到EditLog,这带来一个问题,启动的时间越长EditLog中的内容会更多,下次再做合并的时候(这个合并我们称为checkpoint),会随着EidtLog文件的大小增加合并的时间,HDFS针对这个问题设置了两种机制进行条件合并,例如配置EditLog达到多大做一次合并,或者离上次合并过了多久做一次合并。 但是如果NameNode合并文件占用过多的资源,可能会引发其他的问题。那么如何来避免这样一个问题呢?后续我们会介绍,如何用
SecondaryNameNode来避免这个问题。
FSImage文件格式如下:

HDFS读书笔记-了解NameNode(二)
  

当namenode重启加载fsimage时,就是按照如下格式协议从文件流中加载元数据信息。从fsimag的存储格式可以看出,fsimage保存有如下信息:

一、加载Img头信息,如下:

          1、 imgVersion(int):当前image的版本信息

          2、namespaceID(int):用来确保别的HDFS instance中的datanode不会误连上当前NN。

          3、numFiles(long):整个文件系统中包含有多少文件和目录

          4、genStamp(long):生成该image时的时间戳信息。

二 、如果加载目录,包含以下信息:

          1、path(String):该目录的路径,如”/user/build/build-index”

          2、replications(short):副本数(目录虽然没有副本,但这里记录的目录副本数也为3)

          3、mtime(long):该目录的修改时间的时间戳信息

          4、atime(long):该目录的访问时间的时间戳信息

          5、blocksize(long):目录的blocksize都为0

          6、numBlocks(int):实际有多少个文件块,目录的该值都为-1,表示该item为目录

          7、nsQuota(long):namespace Quota值,若没加Quota限制则为-1

          8、dsQuota(long):disk Quota值,若没加限制则也为-1

          9、username(String):该目录的所属用户名

          10、group(String):该目录的所属组

          11、permission(short):该目录的permission信息,如644等,有一个short来记录。

三、如果加载文件,则还会额外包含如下信息:

          1、blockid(long):属于该文件的block的blockid,

          2、numBytes(long):该block的大小

          3、genStamp(long):该block的时间戳

    当该文件对应的numBlocks数不为1,而是大于1时,表示该文件对应有多个block信息,此时紧接在该fsimage之后的就会有多个blockid,numBytes和genStamp信息。

    因此,在namenode启动时,就需要对fsimage按照如下格式进行顺序的加载,以将fsimage中记录的HDFS元数据信息加载到内存中。
BlocksMap
    最初我们提到过FSImage中没有block到机器列表的映射关系的原因。每一个DataNode启动的时候会通过BlockReport将当前机器所有block信息汇报给NameNode。汇报的相关信息就是维护在BlockMaps中的,
    BlocksMap结构如下:
HDFS读书笔记-了解NameNode(二)


    我们前面提到,FSImage中维护的是文件和block的关系,那么block和机器的关系便是从BlocksMap中获取的。
    BlocksMap维护了三种关系:
          1、file-blcoks
           2、block-datanodelist
           3、datanode-blocks
从上图中我们也可以看到,BlocksMap中的BlockInfo中维护了包括:
          1、blockid,块ID。
          2、块大小。
          3、块的修改时间戳。
          4、块对应的文件。
          5、块对应的机器列表信息。 
DataNode列表
    在上图中已经看到,每一个BlockInfo上都有一个DN1,DN2,DN3其实就是一个block在三台机器上的备份。每一个DataNode对应的是一个Object[]的三元数组,prev表示当前block在该机器上的上一个block,next表示当前block在该机器上的下一个数组。目的很简单,查询一个DataNode上的所有BlockList需求非常少。这样做一来可以节省大量的内存(我们说过,内存会成为NameNode的瓶颈哦),二来直接根据next的指向就可以获取一个DN上的所有blocklist数据。
CorruptReplicationMap 
    简单来理解,在DN上有问题的block(磁盘坏,校验不对)都会在这里,下一次DN做心跳的时候有问题的block会返回给DN并删除。
UnderReplicationMap
    默认的block副本数目是3,没有达到这个数目(磁盘坏了,DN挂了)的都会在这里,并且离的越远,数据迁移优先级会越高。
PeddingReplicationMap
    block坏了,咱要做数据拷贝吧,在迁移中的5分钟没有成功的就认为失败,则添加到neededReplicationBlocks中,以便下次再做数据拷贝。


    本篇文章,我们简单的介绍了NameNode的基本数据结构,但是对于NameNode的单点问题,checkpoint的问题,包括文中提到的SecondaryNameNode等并没有做详细的介绍。
下一篇:

HDFS读书笔记-如何让NameNode高可用(三)

展开阅读全文

没有更多推荐了,返回首页