NameNode管理档案系统的命名空间。它维护着档案系统树及整棵树内所有的档案和目录。这些信息以两个档案形式永久保存在本地磁碟上命名空间镜像档案和编辑日誌档案。NameNode也记录着每个档案中各个块所在的数据节点信息,但它并不永久保存块的位置信息,因为这些信息在系统启动时由数据节点重建。
基本介绍
- 外文名NameNode
节点介绍
HDFS集群有两类节点,并以管理者-工作者模式运行,即一个NameNode(管理者)和多个DataNode(工作者)。一个HDFS cluster包含一个NameNode和若干的DataNode,NameNode(以下简称nn)是master,主要负责管理hdfs档案系统,具体地包括namespace管理(其实就是目录结构),block管理(其中包括 filename->block,block->datanode list的对应关係)。nn提供的是始终被动接收服务的server,主要有四类协定接口ClientDatanodeProtocol接口、ClientProtocol接口、DatanodeProtocol接口、NamenodeProtocol接口。DataNode(以下简称dn)主要是用来存储数据档案,HDFS将一个档案分割成一个个的block,这些block可能存储在一个DataNode上或者是多个DataNode上。dn负责实际的底层的档案的读写,如果客户端client程式发起了读hdfs上的档案的命令,那幺将这些档案分成block,然后nn将告知client这些block数据是存储在哪些dn上的,之后,client将直接和dn互动。
还有一个重要的节点Secondary NameNode,该部分主要是定时对NameNode进行数据snapshots进行备份,这样儘量降低NameNode崩溃之后,导致数据的丢失,其实所作的工作就是从nn获得fsimage和edits把二者重新合併然后发给nn,这样,既能减轻nn的负担又能保险地备份。
数据结构
FSdirectory
FSDirectory存储整个档案系统的目录状态,对整个目录结构的管理通过调用FSImage和FSEditLog的方法从namenode本地磁碟读取元数据信息和向本地磁碟写入元数据信息,并登记对目录结构所作的修改到日誌档案。,FSDirectory保存了档案名称和数据块的映射关係。INode是对档案系统目录结构中一个节点的抽象
INodeFile和INodeDirectory均继承自INode类,分别表示档案节点和目录节点。
INodeFile类中最重要的数据结构是BlockInfo blocks[],它记录了一个档案所包含的所有Block,成员方法的操作大都与Block相关
INodefileUnderConstruction表示正在都建的档案
INodeDirectory的关键数据结构是List<INode> children记录了目录下所有的子节点信息
INodeDirectoryWithQuota表示有配额限制的目录,根目录就是这种类型。
FSimage
把档案和目录的元数据信息持久化地存储到fsimage档案中,每次启动时从中将元数据载入到记忆体中构建目录结构树,之后的操作记录在edits log中
定期将edits与fsimage合併刷到fsimage中
loadFSImage(File curFile)用于从fsimage中读入Namenode持久化的信息。fsimage中保存的元数据信息格式如下,hdfs载入和写入时都按照该格式进行
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,表示根目录,设定根目录的配额,修改时间,访问时间和许可权信息。
将这些信息读入记忆体之后,构造一个档案目录结构树,将表示档案或目录的节点填入到结构中。
然后是载入datanode信息(新版已取消该项)
再之后是载入FilesUnderConstruction.
BlocksMap
block->datanode的信息没有持久化存储,而是namenode通过datanode的blockreport获取block->datanode list
BlocksMap负责维护了三种信息
block->datanode list
block->INodeFile
datanode->blocks
这要归功于一个很牛逼的结构Object[] triplets
他是一个三元组,每个block有几个副本,就有几个三元组。三元组的第一个元素表示该block所属的Datanode,类型是DatanodeDescriptor,通过它获得
block->datanode list
第二/三个元素表示该block所在Datanode上的前/后一个block(前驱和后继),类型是BlockInfo,通过它获得datanode->blocks
藉助这个三元组可以找到一个block所属的所有datanode,也可以通过三元组的后两个元素信息找到一个datanode上所有的block。
上面这两个结构介绍之后,nn需要的namespace信息和block信息基本就全了。在nn载入fsimage完成之后,BlocksMap中只有每个block到其所属的datanodes list的对应关係信息还没建立。然后通过dn的blockReport来收集构建。当所有的dn汇报给nn的blockReport处理完毕后,BlocksMap整个结构也就构建完成了。