hadoop文件数据结构在代码里的组成可以分为 storage、block、file、Inode几类
很容易搞混,下面对这几个部分进行分别分析
1storage
Storage的结构图下图:
Storage是系统运行时对应的数据结构。从大到小,Hadoop中最大的结构是Storage,最小的结构是block。
Storage保存了和存储相关的信息(包括节点的类型:namenode/datanode,状态版本,namespace id, 状态的创建时间),它继承了StorageInfo。
Storage包括 protected List<StorageDirectory> storageDirs = new ArrayList<StorageDirectory>();
StorageDirectory是Storage的内部类,
Storage可以存储在多个StorageDirectory内,但是要保证这些文件的版本号是一致的,在namenode/datanoe初始化的时候会读取(还原)存储状态信息。
应用于DataNode的DataStorage,则继承了Storage,总体类图如下:
DataStorage是Storage的子类,专门应用于DataNode。对DataNode的升级/回滚/提交过程,就是对DataStorage的doUpgrade/doRollback/doFinalize分析得到的。
DataStorage提供了format方法,用于创建DataNode上的Storage格式化。
StorageInfo包含了3个字段,分别是layoutVersion:版本号,如果Hadoop调整文件结构布局,版本号就会修改,这样可以保证文件结构和应用一致。
namespaceID是Storage的ID。
StorageDirectory中最重要的方法是analyzeStorage,它将根据系统启动时的参数和我们上面提到的一些判断条件,返回系统现在的状态。StorageDirectory可能处于以下的某一个状态(与系统的工作状态一定的对应):
NON_EXISTENT:指定的目录不存在;
NOT_FORMATTED:指定的目录存在但未被格式化;
COMPLETE_UPGRADE:previous.tmp存在,current也存在
RECOVER_UPGRADE:previous.tmp存在,current不存在
COMPLETE_FINALIZE:finalized.tmp存在,current也存在
COMPLETE_ROLLBACK:removed.tmp存在,current也存在,previous不存在
RECOVER_ROLLBACK:removed.tmp存在,current不存在,previous存在
COMPLETE_CHECKPOINT:lastcheckpoint.tmp存在,current也存在
RECOVER_CHECKPOINT:lastcheckpoint.tmp存在,current不存在 NORMAL:普通工作模式。
StorageDirectory处于某些状态是通过发生对应状态改变需要的工作文件夹和正常工作的current夹来进行判断。状态改变需要的工作文件夹包括:
previous:用于升级后保存以前版本的文件
previous.tmp:用于升级过程中保存以前版本的文件
removed.tmp:用于回滚过程中保存文件
finalized.tmp:用于提交过程中保存文件
lastcheckpoint.tmp:应用于从NameNode中,导入一个检查点
previous.checkpoint:应用于从NameNode中,结束导入一个检查点
有了这些状态,就可以对系统进行状态相关操作。
fsImage是storage的子类,提供了状态的管理功能。FSImage也能够管理多个Storage,而且还能够区分Storage为IMAGE(目录结构)/EDITS(日志)/IMAGE_AND_EDITS(前面两种的组合)。
在namnode初始化的时候,会初始化FSNamesystem, 然后查找StorageDirectory,查找配置文件(dfs.name.edits.dir和 dfs.name.dir)就是正在修改的命名空间文件和命名空间文件,放到List<StorageDirectory> storageDirs 中,循环找出需要进行修复或者回滚的文件内容,进行处理。查找到最新的StorageDirectory,装载image文件(\home\baqun\tmp\dfs\name\current\fsimage其中包括了版本信息、文件个数、最后修改时间、包含的block的信息、权限控制信息、datanode信息、正在创建的文件信息)
(这是一个复杂的过程,把blocks的信息、inode的信息,permission、parent inode然后组装起来 读取datanode\)
然后把edit log也装载进来:读取两个edit文件,一个是之前的edit log,另外一个是正在写的log文件,装载然后merge进内存。
2 datanode
相关类结构如下:
DatanodeInfo和DatanodeID都定义在包org.apache.hadoop.hdfs.protocol。
DatanodeID只包含了一些配置信息(name:hostname:portNumber,storageID,infoPort,ipcPort),DatanodeInfo增加了一些动态信息(使用容量,结余等)。
DatanodeDescriptor是DatanodeInfo的子类,包含了NameNode需要的附加信息。DatanodeDescriptor 包含了DataNode上一些Block的动态信息。DatanodeDescriptor包含了内部类BlockTargetPair,它保存Block和对应DatanodeDescriptor的关联,BlockQueue是BlockTargetPair队列。DatanodeDescriptor包含了两个BlockQueue,分别记录了该DataNode上正在复制(replicateBlocks)和Lease恢复(recoverBlocks)的Block。同时还有一个Block集合,保存的是该DataNode上已经失效的Block。
private BlockQueuereplicateBlocks =new BlockQueue();
private BlockQueuerecoverBlocks =new BlockQueue();
private Set<Block>invalidateBlocks =newTreeSet<Block>();
DatanodeDescriptor提供一系列方法,用于操作上面保存的队列和集合。也提供get*Command方法,用于生成发送到DataNode的命令。
而DatanodeRegistration存储了namenode需要进行验证的一切信息,还包含了StorageInfo(layoutVersion,namespaceID创建时间)
只有DatanodeDescriptor 是放在namenode包中的,其他都是放在protocol包
DataNode中的每个block副本由本机本地文件系统中的两个文件组成。第一个文件包含数据本身,第二个文件是该block的元数据包括该block数据的校验和及该block的 generation stamp。数据文件大小等于该block的实际长度,同时不需要补上额外的空间以达到标准的块大小{!比如该block只有10MB,那么本地文件系统中的数据文件大小就是10MB,而无需在额外补足让它变成标准的128MB}。因此,如果一个block只有标准大小的一半,那么本地磁盘也只需要半个标准block所需的空间。
在每个DataNode启动时,会连接到NameNode执行一个握手。握手的目的是为了验证名字空间ID及DataNode的软件版本。如果其中只要有一个无法与NameNode匹配,那么DataNode会自动关闭。
名字空间ID是在文件系统创建时分配给它的实例编号。名字空间ID会持久化存储在集群的所有节点中。具有不同名字空间ID的节点无法加入到集群中,这就保护了文件系统的数据完整性。
软件版本的一致性是非常重要的,因为不兼容的版本可能会导致数据损坏或丢失,同时在一个具有数千个节点的大规模集群上,很容易会在升级期间忽略掉某些节点,比如它没有在升级之前正确的关闭或者在升级时处于不可用的状态。
允许一个新初始化的并且没有任何名字空间ID的DataNode加入到集群中,它会接受集群的名字空间ID。{这是因为很多情况下我们需要对集群进行扩容,因此HDFS应该允许我们往集群中添加新机器}
在握手过程完成之后,DataNode会与NameNode进行注册。DataNodes会持久化存储它们自己对应的那个唯一的存储ID。存储ID是DataNode的内部标识符,可以保证即使是它更换了IP地址或者端口也能识别出来。存储ID是在DataNode第一次向NameNode进行注册时分配的,之后它就再也不会改变。
DataNode会通过向NameNode发送一个block report来声明它所拥有的block副本。一个block report包含该block的id,世代戳(generation stamp)以及它所持有的block副本长度。当DataNode注册完成之后就会立即发送第一次的block report。之后,会每隔1小时就进行一次block reports发送,从而为NameNode提供关于该集群内的所有block副本的最新位置信息。
在正常情况下,DataNode会向NameNode发送心跳信息以证实它自己正在运行以及它所持有的block副本是可用的。默认的心跳周期是3秒钟。如果NameNode在十分钟内收不到来自某个DataNode的心跳信息,它会认为该DataNode已经不能提供服务,它所持有的block副本就变成了不可用状态。NameNode就会将这些block副本在其他DataNode上创建出来。
来自DataNode的心跳中还会携带一些关于总的存储容量、存储空间使用量及当前正在处理的数据传输量方面的信息。这些统计信息会被用于NameNode的空间分配及负载平衡决定中。
NameNode不会直接联系DataNode,它会通过对心跳的响应信息来向DataNodes发送指令。这些指令包括如下一些命令:
l 复制blocks到其他节点
l 删除本地的block副本
l 重新注册或者关闭节点
l 发送一个即时block report
这些命令对于维护整个系统的完整性是十分重要的,因此就算是在大规模的集群中,保持心跳的通畅也是非常重要的。NameNode每秒可以处理数千个心跳请求而不会影响到其他的NameNode操作。
3 inode*
INode*抽象了文件层次结构。如果我们对文件系统进行面向对象的抽象,一定会得到和下面一样类似的结构图(类INode*):
Hadoop在内存中存储了file/block的层级结构,Inode就是一个最上层的抽象类,存储了普通的信息:修改时间、父node。内部类DirCounts封装了namespace使用和diskspace使用。
INode是一个抽象类,它的两个字类,分别对应着目录(INodeDirectory)和文件(INodeFile)。INodeDirectoryWithQuota,如它的名字隐含的,是带了容量限制的目录。INodeFileUnderConstruction,抽象了正在构造的文件,当我们需要在HDFS中创建文件的时候,由于创建过程比较长,目录系统会维护对应的信息。
INode中的成员变量有:name,目录/文件名;modificationTime和accessTime是最后的修改时间和访问时间;parent指向了父目录;permission是访问权限。HDFS采用了和UNIX/Linux类似的访问控制机制。系统维护了一个类似于UNIX系统的组表(group)和用户表(user),并给每一个组和用户一个ID,permission在INode中是long型,它同时包含了组和用户信息。
INodeDirectory是HDFS管理的目录的抽象,它最重要的成员变量是:
private List<INode>children;
就是这个目录下的所有目录/文件集合。INodeDirectory也是有大量的get和set方法,都很简单。INodeDirectoryWithQuota进一步加强了INodeDirectory,限制了INodeDirectory可以使用的空间(包括NameSpace和磁盘空间)。
INodeFile是HDFS中的文件,最重要的成员变量是:
protected BlockInfo blocks[] =null;
这是这个文件对应的Block列表,BlockInfo增强了Block类。
INodeFileUnderConstruction
INodeFileUnderConstruction保存了正在构造的文件的一些信息,包括clientName,这是目前拥有租约的节点名(创建文件时,只有一个节点拥有租约,其他节点配合这个节点工作)。clientMachine是构造该文件的客户端名称,如果构造请求由DataNode发起,clientNode会保持相应的信息,targets保存了配合构造文件的所有节点。
INodeDirectoryWithQuota
有一定限额的文件目录类
4 fileSystem
程序员通过org.apache.hadoop.fs.FileSystem来和HDFS打交道
子类分布式文件系统包含了dfsClient,用来调用数据
DistributedFileSystem是分布式文件系统的主要实现类:
文件系统之间的交互,通过DFSClient实现
初始化的时候就新建了DFSClient
public void initialize(URI uri, Configuration conf) throws IOException {
setConf(conf);
String host = uri.getHost();
if (host == null) {
throw new IOException("Incomplete HDFS URI, no host: "+ uri);
}
InetSocketAddress namenode = NameNode.getAddress(uri.getAuthority());//localhost/127.0.0.1:9200
this.dfs = new DFSClient(namenode, conf, statistics);
this.uri = NameNode.getUri(namenode);
this.workingDir = getHomeDirectory();
}
5 block
代码结构如下
BlocksMap(主要是FSNamesystem负责管理)保存了Block和它在NameNode上一些相关的信息。其核心是一个map:Map<Block, BlockInfo>。BlockInfo扩展了Block,保存了该Block归属的INodeFile和DatanodeDescriptor,同时还包括了它的前继和后继Block。有了BlocksMap,就可以通过Block找对应的文件和这个Block存放的DataNode的相关信息。
FSDir(FSDataset)对应了hadoop的目录,目录可以是层级嵌套的,因为每一个文件夹规定了所包含的块的个数的限制.
FSDir实现了对block的管理,添加block的时,会优先使用不创建子目录的方式添加(所包含的block个数不到到最大值)。
FSVolume对应了Storage的管理。
datdanode初始化的时候:
storage = new DataStorage();
FSDatasetInterface data = new FSDataset(storage, conf);
将storage和block的信息进行关联管理。
FSDataset包括变量:
FSVolumeSet volumes;
private HashMap<Block,DatanodeBlockInfo> volumeMap = null;
实现了block和datanode信息的关联。
总结:
他们之间的关系可以通过下图来表示
- 大小: 51.2 KB
- 大小: 49.8 KB
分享到:
相关推荐
### Hadoop文件存储结构:深入理解HDFS #### 引言与目标设定 Hadoop分布式文件系统(HDFS)作为一款专为运行在廉价硬件上的分布式文件系统设计,其架构和功能设定旨在应对大规模数据集的高效管理和处理。不同于...
Hadoop 文件上传失败原因分析及解决方法 本文主要讨论了在 Java Web 程序中上传文件到 Hadoop HDFS 文件系统中失败的原因分析及解决方法。通过对问题的分析和解决,可以总结出以下知识点: 1. Hadoop 文件上传失败...
【标题】:“Hadoop文件”通常指的是在Hadoop生态系统中处理和存储的大数据文件。Hadoop是Apache软件基金会开发的一个开源框架,专为分布式存储和处理大规模数据集而设计。它允许用户在廉价硬件上构建大规模可扩展的...
Hadoop源码分析是深入理解Hadoop分布式计算平台原理的起点,...通过对Hadoop源码的分析,开发者可以深入理解分布式系统的内部结构,掌握数据处理和存储的高级技巧,以及学习如何构建一个可靠、可扩展的分布式计算平台。
2. **数据导入**:将数据文件(如data.txt)复制到Hadoop环境,创建Hive数据库和表结构,字段包括电影ID、名称、投票人数、类型、产地、上映时间、时长、年代、评分和首映地点。使用LOAD DATA命令将数据加载到Hive表...
1. 数据存储:Hadoop的分布式特性使其成为存储大量非结构化和半结构化数据的理想平台,如日志、图像和文本等,这些数据往往是机器学习和深度学习的重要输入。 2. 数据预处理:在进行人工智能模型训练之前,通常需要...
这个“hadoop知识结构图”应该是对整个Hadoop生态系统的一个全面概览,包括其主要组件、工作原理以及与其他技术的关联。 Hadoop由Apache软件基金会开发,它的核心组件主要包括HDFS(Hadoop Distributed File System...
### Hadoop分布式文件系统的模型分析 #### 一、引言 Hadoop分布式文件系统(Hadoop Distributed File System, HDFS)是一种高度可靠且具有极高可扩展性的分布式文件系统,能够支持大规模的数据存储需求[1]。HDFS的...
### Hadoop源代码分析知识点...综上所述,Hadoop作为一项强大的分布式计算框架,其设计涵盖了从底层文件系统到上层应用处理的各个方面,通过对Hadoop源代码的深入分析,我们可以更全面地理解其内部工作机制和设计理念。
### Hadoop源代码分析知识点详解 #### 一、Hadoop与云计算的核心技术 Hadoop作为分布式计算领域的核心框架,其源代码分析对于深入理解云计算的底层实现至关重要。Hadoop最初的设计灵感来源于Google的一系列论文,...
021.Hadoop架构分析之集群结构分析.mp4 022.Hadoop架构分析之HDFS架构分析.mp4 023.Hadoop架构分析之NN和DN原生文档解读.mp4 024.Hadoop架构分析之启动脚本分析(集群id的兼容处理与start-allcmd解析与批处理命令...
### Hadoop源代码分析知识点详解 #### 一、Hadoop背景与关键技术介绍 Hadoop作为一款开源的大数据处理框架,其设计灵感源自Google的一系列核心论文。这些论文详细阐述了Google构建其基础设施的方法论和技术原理,...
名称节点维护文件系统的命名空间和块到数据节点的映射,确保文件的层次结构清晰。数据节点则负责存储实际的应用程序数据,并且每个文件块可能有多个副本,确保数据的冗余和容错性。所有服务器通过TCP协议完全互联,...
"Hadoop开发者入门专刊"是针对初学者的教程,它从基础概念开始,逐步引导读者理解Hadoop的核心组件,包括HDFS、MapReduce和YARN,帮助读者建立起对Hadoop体系结构的全面认识。 "Hadoop开发者第一期、第二期、第三期...
Hive则是基于Hadoop的数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供SQL查询功能,使得非编程背景的用户也能方便地操作大数据。 综合这些信息,我们可以推断这个系统可能的工作流程如下: 1. ...
3. **HDFS工作原理**:HDFS采用主从结构,由一个NameNode作为命名节点,管理文件系统的元数据,多个DataNode作为数据节点,存储实际的数据块。数据块复制策略通常为3份,以提供容错能力。 4. **MapReduce工作流程**...
Hadoop文件系统(HDFS)是Hadoop的核心组成部分之一,它提供了一个高吞吐量的数据访问机制,非常适合大型数据集的处理。HDFS的设计目标是在廉价的商品硬件上运行,并能够容忍硬件故障。 ##### 1. 类层次结构 - **...
2. **解压Hadoop**: 解压缩下载的Hadoop文件到你希望的目录,例如`C:\hadoop`. 3. **配置环境变量**: 在系统环境变量中添加`HADOOP_HOME`,值设为Hadoop的安装路径,如`C:\hadoop`。 4. **配置PATH**: 同样在环境...
这个示例程序“Hadoop示例程序合并文件”旨在演示如何在Hadoop环境下整合多个文件,这对于理解Hadoop分布式文件系统(HDFS)的工作原理至关重要。下面将详细阐述Hadoop的核心组件、HDFS的特性以及如何在Hadoop环境中...