1 概述
本文档目的在于对namenode中各种关键的数据结构进行剖析和解释,以方便更好的对namenode的各种处理逻辑和代码结构进行理解。其中包 括对namenode中Namenode和FSNameSystem的程序代码结构,FSDirectory,BlocksMap, CorruptReplicationMap,excessReplicateMap, UnderReplicatedBlocks,PendingReplictiondBlocks等数据结构的介绍。
1.1 代码结构
1.1.1 NameNode
在HDFS中,namenode的服务提供整个HDFS文件系统的namespace管理,块管理等所有服务,metadata所有的相关服务都是 由namenode进程在提供。其中包括 filename->blocksequence (namespace),以及block->machinelist的对应表。其中前者通过fsimage写入到本地文件系统中,而后者是通过每次 HDFS启动时,datanode进行blockreport后在内存中重构的数据结构。绝大部分的情况下,namenode服务进程其实都是在被动的接 收服务请求 -> 进行相应的操作和更新 –> 进行适当的返回。所以,在HDFS的程序代码中,NameNode类其实只是一个用来接收被动接收调用服务的包装,它实现了ClientProtocol 接口,用来接收来自DFSClient的rpc请求;它实现了DatanodeProtocol接口,用来接收来自Datanode的各种服务请求;同时 它还实现了NamenodeProtocol,用来提供跟SecondaryNameNode之间的rpc请求和通信。但实际上,对NameNode的 rpc调用后面的处理逻辑,以及namespace的bookkeeping,blocksmap的维护,并没有在NameNode的程序结构中包含。真 正进行以上数据结构维护的,是HDFS中的FSNamesystem类。对NameNode的各种请求,比如创建,修改,删除,移 动,getLocations的操作,在NameNode内部都是通过FSNamesystem提供的接口对内部数据结构进行的访问。
1.1.2 FSNamesystem
在namenode server中,真正提供对各种关键数据结构的bookkeeping,维护,更新,同步,以及各种操作接口的类,实际上是FSNamesystem类。 FSNamesystem类中维护了许多个关键的数据结构,这些数据结构中维护了整个HDFS中各种metadata的信息。对HDFS的各种操作,不管 操作的请求是来自client,datanode还是secondarynamenode,到最后都会落到FSNamesystem的内部接口 中,FSNamesystem根据各种不同的服务请求来更新,维护内部的各种数据结构,以达到HDFS实时状态的更新。同时,对HDFS的各种操作,绝大 部分情况下是要涉及到这些关键数据结构的操作,以下便是FSNamesystem各种关键数据结构的详细介绍。
1.2 关键数据结构
1.2.1 FSDirectory
在namenode中,对于HDFS整个文件系统的namespace,也就是以 ”/” 为根的整个目录树的管理,就是通过FSDirectory来管理的。HDFS是会将namespace保存到namenode的本地文件系统的一个叫 fsimage的文件中。从该文件中,namenode每次重启都能将整个HDFS的namespace重构。在FSDirectory中,同时也负责对 fsimage相关操作。另外,对HDFS的各种操作,namenode都会记录相应的操作日志,以便周期性的将该日志于fsimage进行合并,生成新 的fsimage。该日志文件也是在namenode本地文件系统中,叫editlog文件。所以FSDirectory中也负责对editlog的相关 操作。
HDFS整个文件系统的namespace在namenode的内存中,是以一颗树的结构来维护的。在HDFS中,不管是目录还是文件,都被看作是 INode,如果是目录,则其实际类标识为INodeDirectory,如果是文件,则其相应的类标识为INodeFile,这两个类都是INode的 派生类。INodeDirectory中包含一个成员数组变量List<INode> children,如果该目录下有子目录或者文件,其子目录或文件的引用就会保存在children列表中。HDFS就是通过这种方式来维持整个文件系统 的目录结构。
1.2.2 FsImage
Namenode会将HDFS的文件和目录元数据 存储在一个叫fsimage的二进制文件中,每次保存fsimage之后到下次保存之间的所有 hdfs操作,将会记录在editlog文件中,当editlog达到一定的大小(bytes,由fs.checkpoint.size参数定义)或从上 次保存过后一定时间段过后(sec,由fs.checkpoint.period参数定义),namenode会重新将内存中对整个HDFS的目录树和文 件元数据刷到fsimage文件中 。Namenode就是通过这种方式来保证HDFS中元数据信息的安全性。
Fsimage是一个二进制文件,当中记录了HDFS中所有文件和目录的元数据信息,在version为-18的hadoop的HDFS image版中,该文件的中保存文件和目录的格式如下:
当namenode重启加载fsimage时,就是按照如下格式协议从文件流中加载元数据信息。从fsimag的存储格式可以看出,fsimage保存有如下信息:
1. 首先是一个image head,其中包含:
a) imgVersion(int):当前image的版本信息
b) namespaceID(int):用来确保别的HDFS instance中的datanode不会误连上当前NN。
c) numFiles(long):整个文件系统中包含有多少文件和目录
d) genStamp(long):生成该image时的时间戳信息。
2. 接下来便是对每个文件或目录的源数据信息,如果是目录,则包含以下信息:
a) path(String):该目录的路径,如”/user/build/build-index”
b) replications(short):副本数(目录虽然没有副本,但这里记录的目录副本数也为3)
c) mtime(long):该目录的修改时间的时间戳信息
d) atime(long):该目录的访问时间的时间戳信息
e) blocksize(long):目录的blocksize都为0
f) numBlocks(int):实际有多少个文件块,目录的该值都为-1,表示该item为目录
g) nsQuota(long):namespace Quota值,若没加Quota限制则为-1
h) dsQuota(long):disk Quota值,若没加限制则也为-1
i) username(String):该目录的所属用户名
j) group(String):该目录的所属组
k) permission(short):该目录的permission信息,如644等,有一个short来记录。
3. 若从fsimage中读到的item是一个文件,则还会额外包含如下信息:
a) blockid(long):属于该文件的block的blockid,
b) numBytes(long):该block的大小
c) genStamp(long):该block的时间戳
当该文件对应的numBlocks数不为1,而是大于1时,表示该文件对应有多个block信息,此时紧接在该fsimage之后的就会有多个blockid,numBytes和genStamp信息。
因此,在namenode启动时,就需要对fsimage按照如下格式进行顺序的加载,以将fsimage中记录的HDFS元数据信息加载到内存中。
1.2.3 BlocksMap
从以上fsimage中加载如namenode内存中的信息中可以很明显的看出,在fsimage中,并没有记录每一个block对应到哪几个 datanodes的对应表信息 ,而只是存储了所有的关于namespace的相关信息 。而真正每个block对应到datanodes列表的信息在 hadoop中并没有进行持久化存储 ,而是在所有datanode启动时,每个datanode对本地磁盘进行扫描,将本datanode上保存的 block信息汇报给namenode,namenode在接收到每个datanode的块信息汇报后,将接收到的块信息,以及其所在的datanode 信息等保存在内存中 。HDFS就是通过这种块信息汇报的方式来完成 block -> datanodes list的对应表构建。Datanode向namenode汇报块信息的过程叫做blockReport ,而namenode将block -> datanodes list的对应表信息保存在一个叫BlocksMap 的数据结构中。
BlocksMap的内部数据结构如下:
如上图显示,BlocksMap实际上就是一个Block对象对BlockInfo对象的一个Map表,其中Block对象中只记录了 blockid,block大小以及时间戳信息,这些信息在fsimage中都有记录 。而BlockInfo是从Block对象继承而来,因此除了 Block对象中保存的信息外,还包括代表该block所属的HDFS文件的INodeFile对象引用以及该block所属datanodes列表的信 息(即上图中的DN1,DN2,DN3,该数据结构会在下文详述)。
因此在namenode启动并加载fsimage完成之后,实际上BlocksMap中的key,也就是Block对象都已经加载到 BlocksMap中,每个key对应的value(BlockInfo)中,除了表示其所属的datanodes列表的数组为空外,其他信息也都已经成 功加载。所以可以说:fsimage加载完毕后,BlocksMap中仅缺少每个块对应到其所属的datanodes list的对应关系信息。 所缺这些信息,就是通过上文提到的从各datanode接收blockReport 来构建。当所有的datanode汇报给namenode的blockReport处理完毕后,BlocksMap整个结构也就构建完成。
1.2.4 BlockInfo中datanode列表数据结构
在BlockInfo中,将该block所属的datanodes列表保存在一个Object[]数组中,但该数组不仅仅保存了datanodes列表,还包含了额外的信息。实际上该数组保存了如下信息:
上图表示一个block包含有三个副本,分别放置在DN1,DN2和DN3三个datanode上,每个datanode对应一个三元组,该三元组 中的第二个元素,即上图中prev block所指的是该block在该datanode上的前一个BlockInfo引用。第三个元素,也就是上图中next Block所指的是该block在该datanode上的下一个BlockInfo引用。每个block有多少个副本,其对应的BlockInfo对象中 就会有多少个这种三元组。
Namenode采用这种结构来保存block->datanode list的目的在于节约namenode内存。由于namenode将block->datanodes的对应关系保存在了内存当中,随着HDFS 中文件数的增加,block数也会相应的增加,namenode为了保存block->datanodes的信息已经耗费了相当多的内存,如果还像 这种方式一样的保存datanode->block list的对应表,势必耗费更多的内存,而且在实际应用中,要查一个datanode上保存的block list的应用实际上非常的少,大部分情况下是要根据block来查datanode列表,所以namenode中通过上图的方式来保存 block->datanode list的对应关系,当需要查询datanode->block list的对应关系时,只需要沿着该数据结构中next Block的指向关系,就能得出结果,而又无需保存datanode->block list在内存中。
1.2.5 CorruptReplicationMap
如上所述,namenode中是通过block->datanode list的方式来维护一个block的副本是保存在哪几个datanodes上的对应关系的。保存在datanodes上的block,常常会因为各种各 样的原因(磁盘损坏,校验错误等)出错,这种情况下,namenode中会将这些datanode上的block标记为Corrupt状态,并记录该 block在哪几台datanode上保存的副本是corrupt的。这些信息,就是保存在CorruptReplicationMap中。 CorruptReplicationMap内部其实就是一个Block-> Collection<DatanodeDescriptor>的TreeMap,namenode中通过该数据结构来记录哪些block的 哪(几)个副本为corrupt状态,并会在随后的将这些记录的block放入到一个 recentInvalidateSets(Map<String, Collection<Block>>)中。
在datanode的每次heartbeat过来namenode的时候,namenode就有机会查询该 recentInvalidateSets,看是否在该汇报的datanode上有被标记为invalidate的block,如果有,就在 heartbeat中返回给该datanode一个cmd,告诉该datanode将该有问题的block进行删除。
1.2.6 UnderReplicatedBlocks
HDFS中的block,通常会对应多个副本,假设某block的副本数是3,那么并不一定在任何时候,该block的可用副本数都能保持为3。原 因是集群中随时都有可能会有硬盘损坏,datanode下线等原因。发生这种情况时,某些block的对应的副本就会下降。HDFS将副本数没有达到其期 望值的block引用保存在UnderReplicatedBlocks数据结构中。UnderReplicatedBlocks其实是一个list列 表,其结构为:ArrayList<TreeSet<Block>>。List中的每一个item其实都是一个 TreeSet,set中是一系列的block引用。UnderReplicatedBlocks将该list中的block按照优先级来分类。优先级由 该block当前副本数和缺少的副本数来决定,也就是说,缺少的副本数越多,标识该block的副本被拷贝到其他datanode上的请求就越紧急,其优 先级也就越高。因此,优先级为0的blocks,就保存在优先级为0的TreeSet中,以此类推。
1.2.7 PendingReplicationBlocks
当namenode发现某些block的可用副本数低于其期望副本数时,在一定时期内就会对该block进行副本拷贝的操作,以将其可用副本数提高 到期望副本数(通常为3)。而正在进行副本拷贝的block,namenode会将其引用保存在PendingReplicationBlocks中,当 该block从一台src datanode拷贝到target datanode的副本拷贝操作时,就会将该block的引用保存在PendingReplicationBlocks中。
在block做副本拷贝时,有些能够很正常的拷贝成功,但是有些拷贝操作因为各种各样的原因,会发生失败,或者超时,默认的超时时间是5分钟。当发 生超时时,namenode会将这些block重新添加到neededReplicationBlocks中,以便接下来重新对其进行副本拷贝操作。 PendingReplicationBlocks中还有一个后台线程,就是这个线程在不停的检查正在做副本拷贝的block是否有超时的现象。
相关推荐
在Hadoop分布式文件系统(HDFS)中,Namenode是关键组件,它负责元数据管理,包括文件系统的命名空间和文件的块映射信息。当Namenode启动失败时,通常与fsimage和edits文件有关,这些文件是Namenode存储元数据的重要...
storageType标识该目录用于保存元数据节点的数据结构。而DataNode的VERSION文件中,blk_文件保存具体的数据块内容,blk_<id>.meta文件保存数据块的属性信息,如版本、类型信息和校验和。 HDFS架构通过这样的设计...
1. **存储目录结构**:在Secondary NameNode的数据存储目录中,存在以下几个关键目录: - `current`:当前最新的检查点信息。 - `previous.checkpoint`:上一个检查点的信息。 - `image`:包含`fsimage`文件。 -...
《HDFSNameNode内存全景》中,我们从NameNode内部数据结构的视角,对它的内存全景及几个关键数据结构进行了简单解读,并结合实际场景介绍了NameNode可能遇到的问题,还有业界进行横向扩展方面的多种可借鉴解决方案。...
开发者需要深入理解HDFS的内部机制,包括文件系统操作流程、NameNode的工作原理以及元数据的存储结构。此外,选择合适的工具,例如分布式数据库系统,也是实现独立持久化存储的关键。可能涉及到的工具有HBase、...
17. **内部表与外部表**:内部表由Hive完全管理,删除时数据也会被删除;外部表只管理表结构,删除表时数据仍保留。 18. **Hive索引**:Hive支持基于桶的索引,用于优化查询性能,但与关系数据库的索引有所不同,...
8. **数据结构与范式**:在数据库设计中,了解数据的三范式(1NF、2NF、3NF)至关重要,它们确保数据的规范化,减少数据冗余和异常。 9. **数据复制与容错**:当DataNode故障时,Namenode会检测到并重新复制数据块...
1. `FSDirectory`:这是NameNode中管理文件系统元数据的关键类,包含了文件和目录的创建、删除、重命名等操作。源码中可以看到如何处理这些操作以及如何更新元数据信息。 2. `BlockManager`:负责HDFS的数据块管理和...
- NameNode:负责存储文件系统的元数据,包括文件系统的目录结构、文件属性等信息。它不存储实际数据,而是存储数据块(blocks)位置的映射。 - DataNode:在集群中实际存储数据。每个DataNode都存储文件系统的数据...
### Hadoop源代码分析——NameNode中的Block Report与相关操作 ...通过上述分析可以看出,Hadoop中`NameNode`与`DataNode`之间通过精心设计的通信机制和数据结构,实现了高效可靠的数据管理和维护功能。
6. **算法与数据结构**:常见排序算法(如归并排序、快速排序)、查找算法、图论问题、动态规划、链表、树等数据结构的实现和应用。 7. **编程与设计**:面向对象设计原则、代码重构、单元测试、软件架构设计、...
HDFS采用主从结构,由NameNode负责元数据管理,DataNode负责数据存储,通过副本策略确保数据的安全性和可靠性。理解HDFS的工作原理和最佳实践,对于优化大数据存储和访问至关重要。 HBase作为基于Hadoop的分布式列...
在大数据领域,Hadoop平台因其高效、可扩展的数据处理能力而备受关注。本文将深入探讨在Hadoop平台下数据存储的...随着技术的不断进步,Hadoop将继续在大数据领域发挥关键作用,为企业提供更强大的数据存储和处理能力。
NameNode是HDFS的元数据管理器,它维护文件系统命名空间,也就是文件和目录的层次结构,以及文件到数据块的映射。NameNode将这些元数据存储在内存中,以便快速查询,同时也定期将元数据持久化到硬盘上的日志文件中,...
HDFS采用了主从结构,由一个NameNode作为主节点管理元数据,多个DataNode作为从节点存储数据块。HDFS的特性包括高可用性、可扩展性和容错性,这使得它成为处理和存储海量数据的理想选择。 接下来,“Hadoop学习总结...
本文将深入剖析HDFS文件读取流程,重点探讨客户端如何打开文件、NameNode的角色以及其内部结构对读取过程的影响。 ##### 1.1 客户端文件打开操作 客户端在HDFS中打开文件的过程始于`DistributedFileSystem.open()`...
- **结构化数据**:通常来自企业内部的交易系统,如数据库中的数据,易于管理和分析。 - **实时数据**:连续生成并需要实时处理的数据,如传感器数据。 - **GIS数据**:地理信息系统数据,包含地理位置信息。 2....
HDFS采用主从结构,由NameNode作为主节点负责元数据管理,DataNode作为从节点存储数据。HDFS的特点包括高容错性、高扩展性和流式数据访问。 2. MapReduce:MapReduce是Hadoop用于大规模数据处理的编程模型,由“Map...
通过`datanodeMap`(一个存储`StorageID`到`DatanodeDescriptor`映射的数据结构),NameNode能够快速找到与当前注册请求相对应的`DatanodeDescriptor`。 - **步骤4:处理Storage变化** 如果发现DataNode的`...