《Hadoop中HDFS源代码分析.docx》由会员分享,可在线阅读,更多相关《Hadoop中HDFS源代码分析.docx(33页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、 Hadoop中HDFS源代码分析目 录一、Hadoop系统基础- 1 -1.1、Hadoop简介- 1 -1.2、Hadoop的项目组成- 2 -1.3、Hadoop基本架构模型- 3 -1.4、Hadoop集群- 5 -二、Hadoop文件系统(HDFS)- 6 -2.1、HDFS主要功能组件- 7 -2.2、HDFS体系结构- 8 -2.3、NameNode- 9 -2.4、DataNode- 10 -三、HDFS的实现代码分析- 11 -3.1、org.apache.hadoop.io- 11 -3.2、RPC的实现方法- 13 -3.2.1、Client类- 13 -3.2.2、Se
2、rver类- 15 -3.2.3、RPC类- 17 -3.2.4、HDFS通信协议组- 18 -3.3、名称节点的实现方法- 20 -3.3.1、FSImage类- 21 -3.3.2、FSEditLog类- 22 -3.3.3、FSNamesystem类- 23 -3.4、数据节点的实现方法- 27 -3.4.1、数据节点的设计- 27 -3.4.2、数据处理的设计- 28 -3.5、客户端实现方法- 30 -3.5.1、数据读取的设计- 30 -3.5.2、数据写入的设计- 32 -四、总结- 33 -一、Hadoop系统基础1.1、Hadoop简介Hadoop由ApacheSoftwar
3、eFoundation公司于2005年秋天作为Lucene的子项目Nutch的一部分正式引入。它受到最先由Google开发的MapReduce和GoogleFileSystem的启发,2006年3月份,MapReduce和NutchDistributedFileSystem(NDFS)分别被纳入称为Hadoop的项目中。Hadoop是最受欢迎的在Internet上对搜索关键字进行内容分类的工具,但它也可以解决许多要求极大伸缩性的问题。在Hadoop中实现了Google的MapReduce算法,它能够把应用程序分割成许多很小的工作单元,每个单元可以在任何集群节点上执行或重复执行。此外,Hadoo
4、p还提供一个分布式文件系统用来在各个计算节点上存储数据,并提供了对数据读写的高吞吐率。由于应用了map/reduce和分布式文件系统,使得Hadoop框架具有高容错性,它会自动处理失败节点。Hadoop是以一种可靠、高效、可伸缩的方式进行处理的。Hadoop是可靠的,因为它假设计算元素和存储会失败,因此它维护多个工作数据副本,确保能够针对失败的节点重新分布处理。Hadoop是高效的,因为它以并行的方式工作,通过并行处理加快处理速度。Hadoop还是可伸缩的,能够理PB级数据。此外,Hadoop依赖于社区服务器,因此它的成本比较低,任何人都可以使用。Hadoop带有用 Java 语言编写的框架,
5、因此运行在Linux生产平台上是非常理想的。Hadoop上的应用程序也可以使用其他语言编写,比如C+。Hadoop是一个能够对大量数据进行分布式处理的软件框架。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力高速运算和存储。在很多大型网站上都已经得到了应用,如亚马逊,Facebook,雅虎,新浪,淘宝等。1.2、Hadoop的项目组成 Hadoop的子项目1. Hadoop Common:就是原来的Hadoop Core,它是一系列分布式文件系统和通用I/O 的组件和接口。是整个Hadoop项目的核心,其他Hadoop子项目都是在Hadoop Common的基础上发展
6、起来的。2. Avro:一种提供高效、跨语言RPC 的数据序列系统,持久化数据存储。3. ZooKeeper:一个分布式的、高可用性的协调服务。用于解决分布式系统中一致性问题,是Chubby的开源实现。4. HBase:是一个开源的、基于列存储模型的分布式数据库,是Bigtable 的开源实现。HBase 使用HDFS 作为底层存储,同时支持MapReduce的批量式计算和点查询(随机读取)。5. HDFS:提供高吞吐量的分布式文件系统,是 GFS 的开源实现。HDFS 是分布式计算的存储基础。HDFS具有高容错性,可以部署在廉价的硬件设备上,适合那些有大数据集的应用,并且提供对数据读写的高吞
7、吐量。HDFS能够提供对数据的可扩展访问,通过简单地往集群里添加节点就可以解决大量客户端同时访问的问题。HDFS支持传统的层次文件组织结构,同现有的一些文件系统类似,如可以对文件进行创建、删除、重命名等操作。6. MapReduce:大型数据的分布式处理模型,以在大型集群上执行分布式应用的简单性和可用性著称。Hadoop的MapReduce是Google的MapReduce的开源实现。MapReduce是一种简化的并行计算模型,由Map和 Reduce组成,分别进行任务的分解和对结果的汇总。7. Hive:是一种提供数据摘要和查询功能的分布式数据仓库,管理HDFS中存储的数据。Hive支持的查
8、询是类似SQL方式的陈述语言:HiveQL ,这种查询被编译进MapReduce的job用以Hadoop的执行。8. Pig:是在MapReduce上构建的一种高级的数据流语言,用以检索非常大的数据集,它是Sawzall的开源实现。Sawzall是一种建立在 MapReduce基础上的领域语言,它的程序控制结构(如 if、while 等)与 C语言无异,但它的领域语言语义使它完成相同功能的代码比MapReduce的C+代码简洁。9. Chukwa:一个用来管理大型分布式系统的数据采集系统。Chukwa 运行HDFS 中存储数据的收集器,它使用MapReduce 来生成报告。1.3、Hadoop
9、基本架构模型Hadoop框架中最核心的设计就是HDFS和MapReduce。HDFS是Hadoop分布式文件系统的缩写,为分布式计算存储提供了底层支持。MapReduce的思想是由Google的一篇论文所提及而被广为流传的,简单的一句话解释MapReduce就是任务的分解与结果的汇总。MapReduce和HDFS的关系如下图: Hadoop内部结构图MapReduce是依赖于HDFS实现的。通常MapReduce会将被计算的数据分为很多小块,HDFS会将每个块复制若干份以确保系统的可靠性,同时它按照一定的规则将数据块放置在集群中的不同机器上,以便MapReduce在数据宿主机器上进行最便捷的计
10、算。主从式是云计算系统的一种典型架构的方法,系统通过主节点屏蔽底层的复杂结构,并向用户提供方便的文件目录映射。Hadoop 中也采用了主从式的架构技术,如图所示:Hadoop主从结构1.4、Hadoop集群Hadoop框架可在单一的Linux平台上使用(在开发和调试时),但是使用存放在机架上的商业服务器才能发挥它的力量。这些机架组成一个Hadoop集群。它通过集群拓扑决定如何在整个集群中分配作业和文件。二、Hadoop文件系统(HDFS)HDFS是Hadoop应用中的一个必不可少的一个分布式文件系统,它将海量数据分布存储在严格大集群的多台计算机上,把文件进行分块存储,块的大小(通常为64MB)
11、和复制的块数量在创建文件时由客户机决定。为实现容错自动进行分块复制。Hadoop文件系统(Hadoop Distributed File System,HDFS)和现有的分布式文件系统相似,是一个运行在普通的硬件之上的分布式文件系统,然而它与其他分布式文件系统也存在着一定的差别。HDFS具有高容错性,可以部署在低成本的硬件之上,同时HDFS放松了对POSIX的需求,使其可以以流的形式访问文件数据,从而提供高吞吐量地对应用程序的数据进行访问,适合大数据集的应用程序。HDFS采用Master/Slave(主/从)结构,整个集群由一个名称节点(Name Node)和多个数据节点(DataNode)组
12、成。NameNode主要负责管理文件命名空间和客户端访问的主服务器,而DataNode则负责对存储进行管理。2.1、HDFS主要功能组件2.2、HDFS体系结构由图可知,名称结点(NameNode)上保存着控制数据结点(DataNode)信息的元数据(Metadata)。客户端Client可以通过NameNode对元数据进行操作,也可以直接对DataNode进行读和写操作。集群中一台机器上只运行一个NameNode实例,而集群中其它机器分别运行一个DataNode实例。NameNode是一个中心服务器,负责管理文件系统的名字空间以及客户端对文件的访问,用户能够以文件的形式在上面进行名字空间操作
13、,比如打开、关闭、重命名文件或目录,同时NameNode还决定了数据块到数据节点的映射关系。NameNode也可以称为管理文件系统的元数据。集群中每一个节点配置一个DataNode,每个DataNode负责管理它所在节点上的数据存储。从内部看,一个文件被分成一个或多个数据块,这些块存储在一组DataNode上。同时,DataNode负责处理文件系统客户端的读写请求,在NameNode的统一调度下进行数据块的创建,删除和复制。2.3、NameNodeNameNode的功能由如下几点组成:(1)管理元数据和文件块管理元数据指管理元数据信息。元数据信息包括名字空间、文件到文件块的映射、文件块到数据节
14、点的映射三部分。管理文件块包括创建新文件块、文件复制、移除无效文件块以及回收孤立文件块等内容。(2)管理命名空间NameNode管理文件系统的命名空间。任何对文件系统元数据产生修改的操作,NameNode都会使用事务日志记录(下称EditLog)来表示;同样地,修改文件的副本系数也将往Editlog中插入一条记录,NameNode将Editlog存储在本地操作系统的文件系统中。同时,文件系统的命名空间被存储在一个称之为Fslmage(映像文件)的文件中,包括文件的属性、文件块到文件的映射以及文件块到数据节点的映射等内容,FsImage文件也是存放在NameNode所在的本地文件系统中。(3)监
15、听请求和处理请求监听请求指监听客户端事件和DataNode事件。客户端事件包含名字空间的创建和删除,文件的创建、读写、重命名和删除,文件列表信息获取等信息。DataNode事件主要包括文件块信息、心跳响应、出错信息等。处理请求指处理上面的监听请求事件并返回结果。(4)心跳检测DataNode会定期将自己的负载情况通过心跳信息向NameNode汇报。Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表。 Name
16、Node决定是否将文件映射到DataNode的复制块上。对于最常见的3个复制块,第一个复制块存储在同一机架的不同节点上,最后一个复制块存储在不同机架的某个节点上。实际的I/O事务并没有经过NameNode,只有表示DataNode和块的文件映射的元数据经过NameNode。当外部客户机发送请求,要求创建文件时,NameNode会以块标识和该块的第一个副本的DataNodeIP地址作为响应。这个NameNode还会通知其他将要接收该块的副本的DataNode。NameNode在一个称为FsImage的文件中存储所有关于文件系统名称空间的信息。这个文件和一个包含所有事务的记录文件(这里是EditL
17、og)将存储在NameNode的本地文件系统上。FsImage和EditLog文件也需要复制副本,以防文件损坏或NameNode系统丢失。2.4、DataNode DataNode的功能主要包括以下几个方面:首先,是数据块的读写。一般是文件系统客户端需要请求对指定DataNode进行读写操作,DataNode通过DataNode的服务进程与文件系统客户端打交道。同时,DataNode进程与NameNode统一结合,对是否需要对文件块的创建、删除、复制等操作进行指挥与调度,当与NameNode交互过程中收到了可以执行文件块的创建、删除或复制操作的命令后,才开始让文件系统客户端执行指定的操作。具体
18、文件的操作并不是DataNode来实际完成的,而是经过DataNode许可后,文件系统客户端进程来执行实际操作。其次,是向NameNode报告状态。每个DataNode节点会周期性地向NameNode发送心跳信号和文件块状态报告,以便NameNode获取到工作集群中DataNode节点状态的全局视图,从而掌握它们的状态。如果存在DataNode节点失效的情况时,NameNode会调度其它DataNode执行失效结点上文件块的复制处理,保证文件块的副本数达到规定数量。最后,是执行数据的流水线复制。当文件系统客户端从NameNode服务器进程中获取到要进行复制的数据块列表(列表中包含指定副本的存放
19、位置,亦即某个DataNode结点)后,会首先将客户端缓存的文件块复制到第一个DataNode节点上,此时并非整个块都复制到第一个DataNode完成以后才复制到第二个DataNode节点上,而是由第一个DataNode向第二个DataNode节点复制,如此反复进行下去,直到完成文件块及其块副本的流水线复制。三、HDFS的实现代码分析3.1、org.apache.hadoop.io由于Hadoop 的MapReduce和HDFS都有通信的需求,需要对通信的对象进行序列化。Hadoop并没有采用Java的序列化,而是引入了它自己的系统。org.apache.hadoop.io包中定义了大量的可序
20、列化对象,他们都实现了Writable接口。实现了Writable接口的一个典型例子如下:Java代码:public class MyWritable implements Writable/Some dataprivateintcounter; privatelongtimestamp; public void write(DataOutputout) throws IOExceptionout.writeInt(counter);out.writeLong(timestamp);public void readFields(DataInputin) throws IOExceptionco
21、unter=in.readInt();timestamp=in.readLong();public static MyWritable read(DataInputin) throws IOExceptionMyWritablew=newMyWritable();w.readFields(in);returnw;其中的write和readFields分别实现了把对象序列化和反序列化的功能,是Writable接口定义的两个方法。下图给出了庞大的org.apache.hadoop.io中对象的关系。org.apache.hadoop.io中对象的关系这里,把ObjectWritable 标记为红色
22、,是因为相对于其他对象,它有不同的地位。当我们讨论Hadoop的RPC时,我们会提到RPC上交换的信息,必须是Java的基本类型,String和Writable接口的实现类,以及元素为以上类型的数组。ObjectWritable对象保存了一个可以在RPC上传输的对象和对象的类型信息。这样,我们就有了一个万能的,可以用于客户端/服务器间传输的Writable对象。例如,我们要把上面例子中的对象作为RPC请求,需要根据MyWritable创建一个ObjectWritable,ObjectWritable往流里会写如下信息对象类名长度,对象类名,对象自己的串行化结果这样,到了对端,ObjectWri
23、table可以根据对象类名创建对应的对象,并解释串行。应该注意到,ObjectWritable依赖于WritableFactories,那存储了Writable子类对应的工厂。我们需要把MyWritable的工厂,保存在WritableFactories中(通过WritableFactories.setFactory)。3.2、RPC的实现方法RPC(Remote Procedure Control)机制是网络应用的一种高级通信范例,它允许程序员使用各种专门化的、隐藏基本网络机制细节的过程调用来编写网络应用程序和使用远程或本地的资源。RPC通信实现了一种专门为支持网络应用程序而设计的、使调用者
24、无需了解底层网络的CS系统。DFSClient是HDFS的客户端,它能够连接到HDFS执行指定任务,那么它要与NameNode与DataNode基于一定的协议来进行通信。HDFS之间的通信是采用CS模式。请求程序相当一个客户机,服务提供程序相当一个服务器。为了解决这些客户机服务器之间的通信,Hadoop引入了RPC机制。在org.apache.hadoop.ipc包中,定义了进程间通信的Client端与Server端的抽象。3.2.1、Client类Client类主要处理的是与服务器进行连接的工作,包括连接的创建、监控等。它定义的五个内部类分别是:Client.Call,Client.Conn
25、ectionId,Client.ParallelResults,Client.Connection和Client.ParallelCall。Client.Call是客户端调用的一个抽象,主要定义了一次调用所需要的条件,以及修改Client客户端的一些全局统计变量。Client.Connectionld是一个连接的实体类,标识了一个连接实例的Socket地址、用户信息UserGrouplnformation和连接的协议类。每个连接都是通过一个该类的实例唯一标识。Client.ParallelResults是用来收集在并行调用环境中结果的实体类。 Client.ParallelCall该类继承自上
26、面的内部类Call,只是返回值使用上面定的ParallelResults实体类来封装。Client.Connection是一个连接管理内部线程类,该内部类是一个连接线程,继承自Thread类。它读取每一个Call调用实例执行后从服务端返回的响应信息,并通知其他调用实例。每一个连接具有一个连接到远程主机的Socket,该Socket能够实现多路复用,使得多个调用复用该Socket,客户端收到的调用得到的响应可能是无序的。Client的主体类图如下图所示。 RPC Client的主体类图3.2.2、Server类Server类是服务端的抽象实现,定义了一个抽象的IPC服务。该IPC服务器接收Cli
27、ent发送的参数值,并返回响应值。同时,作为IPC模型的服务端,它要维护Client端到Server端的一组连接。 需要注意的是,这里的Server类是个抽象类,这表明,Server提高了一个架子,Server的具体功能需要由实现call方法的具体类来实现。同样,Server类定义了5个内部类,它们分别是Server.Call内部类,Server.Connection内部类,Server.Listener内部类,Server.Handler内部类和Server.Responder内部类。下面,我们来分析Server类中定义的几个内部类,如图所示。 RPC Server的主体类图Server.C
28、all类是Server端使用队列维护的调用实体类,它定义的属性包括:客户端调用Call的ID,客户端调用传递的参数(param),到客户端的连接实例(connection),向客户端调用发送响应的时间戳(timestamp)和向客户端调用响应的字节缓冲区(response)。Server.Connection类维护了一个来自客户端的Socket连接。它处理版本校验,读取请求并把请求发送给请求处理线程,接收处理结果并把结果发送给客户端。Server.Listener类是继承自Thread线程类,用来监听服务器Socket,并为Handler处理器线程创建处理任务。Server.Handler类是
29、一个处理线程类,负责处理客户端的全部调用。该线程主要的任务是:真正地实现了处理来自客户端的调用,并设置每个相关调用的响应。关于响应的实现,有个具体实现的线程类Server.Responder。Server.Responder该线程类实现发送RPC响应到客户端。3.2.3、RPC类RPC类给出了一个简单的RPC机制,它的协议是基于一个Java接口,协议界定,所有的参数和返回类型必须是下面之一:(1)基本类型:boolean、byte、char、short、int、long、float、double,或void;(2) String;(3) org.apache.hadoop.io.Writabl
30、e;(4)上述类型的数组。RPC.Invoker内部类实现了java.1ang.reflect.InvocationHandler接口,是一个代理实例的调用处理程序实现类。该内部类列出了客户端调用,并返回调用处理结果。RPC.Invoker使用了RPC.Invocation。Invocation封装了一个远程调用的所有相关信息,包括方法的名称和参数,它实现了Writable,Configurable接口,可以串行化。RPC.ClientCache内部类定义了一个缓存Map:通过客户org.apache.hadoop.ipc.Client的SocketFactory可以快速取出对应的Client
31、实例。RPC.Server内部类是RPC的核心,它继承自org.apache.hadoop.ipc.Server抽象类,实现的核心的是调用处理方法call()。RPC的主体类图如图所示。3.2.4、HDFS通信协议组通过对HDFS的RPC机制的研究,我们知道在org.apache.hadoop.ipc包中,Hadoop实现了基于IPC模型的RPC机制,可以不需要像Java中实现的RMI机制一样,在RPC调用的C/S两端分别创建Stub和Skeleton,而是通过一组协议来进行RPC调用就可以实现通信。这主要是由于Hadoop所采用的序列化机制简化了RPC调用的复杂性。Hadoop定义了自己的通
32、信协议,这些协议都是建立在TCP/IP协议之上的,规范了通信两端的约定。HDFS通信协议组的主体类图如图所示。HDFS通信协议组包括:CliemDataNodeProtocol:该协议是客户端进程和DataNode进程之间通信所使用的协议,用户通过ClientProtocol协议可以操纵HDFS的目录命名空间、打开与关闭文件流等;ClientProtocol:该协议是用户进程(包括客户端进程与DataNode进程)与NameNode进程之间进行通信所使用的协议;DataNodeProtocol:该协议是DataNode进程与NameNode进程进行之间通信所使用的协议,例如发送心跳报告和块状态
33、报告;InterDataNodeProtocol:该协议是DataNode进程之间进行通信的协议,例如客户端进程启动复制数据块,此时可能需要在DataNode结点之间进行块副本的流水线复制操作;NameNodeProtocol:该协议是NameNode进程与SecondaryNameNode进程之间进行通信的协议。3.3、名称节点的实现方法NameNode主要是实现了NameNode服务器进程与DataNode进程、文件系统客户端进程,以及SecondaryNameNode进程进行交互过程中一些重要的基本的操作,具体表现为,NameNode实现了ClientProtocol协议来与客户端交互,
34、实现了DataNodeProtocol协议来与DataNode进行交互,实现NameNodeProtocol协议来与SecondaryNameNode进行交互。一个NameNode提供的主要服务是基于其内部定义的FSNamesystem属性来实现的,因此可以料想它实现的复杂性。下面首先介绍了FSlmage(映像文件)和FSEditLog的设计和实现,为分析FSNamesystem做准备,接着分析FSNamesystem的相关类,以便更好地理解FSNamesystem的实现,由此来理解NameNode的实现。3.3.1、FSImage类FSlmage类保存的是文件系统的目录树。FSImage类中
35、定义了相关的升级回滚提交等操作来保持元数据的持久化。FSImage类支持参数importCheckpoint,该参数用于在某一个checkpoint目录里加载HDFS的目录信息,并更新到当前系统。FSImage类使用loadFSImage(FilecurFile)方法读入NameNode持久化信息,该方法是FSImage中最重要的方法之一。该方法的对应方法是saveFSImage(File newFile)。FSlmage类的主体部分类图如图所示。3.3.2、FSEditLog类FSEditLog类维护一个记录对文件系统命名空间进行修改操作的日志文件。EditLogOutputStream类是
36、一个用来支持将EditLog日志文件中内容持久化(写入)到存储目录中的通用抽象类。一个EditLog日志文件也是通过流式进行写的,而且定时对日志文件进行同步,写入持久存储中,其中支持写入字节和Writable类型数据;在同步的过程中,需要记录同步统计数据;当EditLog日志文件达到一定大小的时候,需要启动检查点进程来进行处理。FSEditLog.EditLogOutputStream继承了EditLogOutputStream类,它实现了EditLogOutputStream类中定义的抽象方法能够在一个本地文件(local file)中存储EditLog日志文件。在执行流式追加写的过程中,设
37、置了两个重要的数据缓冲区,bufReady与bufCurrent,通过这两个数据缓冲区的切换,将不断要追加写入EditLogFileOutputStream流对象中的数据,同步到本地磁盘文件中。EditLoglnputStream类是一个用来支持读取本地存储目录中对应的文件,从而得到EditLog日志文件。FSEditLog.EditLogFilelnputStream类提供了对EditLog日志文件基于流的读取操作。3.3.3、FSNamesystem类由于FSNamesystem的实现比较复杂,因此对FSNamesystem的相关类进行分析,以便更好地理解FSNamesystem类的实现。
38、(1)HostNodesMap类HostNodesMap类用来保存DataNode结点的主机到DataNodeDescriptor数组的映射的类,其实一个DataNodeDescriptor中已经包含了DataNode所在主机的字符串的信息。可见,对于一个DataNode结点,也就是对应的一台主机上,可以存在多个DataNode进程,因此存在一个DataNode主机到一组DataNode进程信息描述的映射。但是一般来说,一个主机上只单独设置一个DataNode进程。通过上面叙述,可以想到,作为一个Host2NodesMap类,应该提供向map映射表中添加对的操作,删除指定Host对应的Data
39、NodeDescriptor ,获取到指定Host对应的DataNodeDescriptor 信息,等等。(2)NetworkTopology类NetworkTopology类表示一个具有树状网络拓扑结构的计算机集群,例如,一个集群可能由多个数据中心(Data Center)组成,在这些数据中心分布着为计算需求而设置的很多计算机的机架(Rack)。NetworkTopology实现了一个树状的拓扑结构抽象。NetworkTopology类定义的网络拓扑对应选择数据块副本的位置很重要。例如在一个层次型的网络中,接到同一个交换机的两个节点间的网络速度会比跨越多个交换机的两个节点间的速度快,但是如果
40、某交换机故障,那么它对接到它上面的两个节点会同时有影响,但跨越多个交换机的两个节点,这种影响会小的多。(3)DNSToSwitchMapping接口类DNSToSwitchMapping接口类配合上面的NetworkTopology,用于确定某一个节点的网络位置信息。该类定义了DNSnameIPaddress到RacklD之间转换的解析器,并将解析后的RackID键值加入到缓存cache中。(4)ReplicationTargetChooser类ReplicationTargetChooser类是对指定的块副本的存放位置进行定位选择的实现类。对指定块副本的存放位置进行定位选择的基本策略是:如果
41、一个写操作是在一个DataNode上,第一个块副本被存放在本地机器上,否则就随机选择一个DataNode来存放第一个块副本;第二个块副本存放在与第一个块副本不同的机架的一个DataNode上;第三个块副本存放在与第一个块副本相同的机架上,也就是同一个DataNode上。该类主要就是针对块副本的存放位置的选择,因此在选择指定机架的过程中,需要获取到指定DataNode的DataNodeDescriptor信息,通过它来验证是否可以存放块副本。在三个块副本都已经存放好以后,可能还需要对指定块的块副本进行检查验证,是否满足实际的存储需要,比如满足副本因子。(5)HostsFileReader类Hos
42、tsFileReader类用来跟踪DataNode的,哪些DataNode允许连接到NameNode,哪些不能够连接到NameNode,都在该类中指定的列表中记录着。该类能够通过refresh方法将DataNode记录列表加载到内存。(6)GenerationStamp类GenerationStamp类是Hadoop文件系统的时间戳的实现,通过它可以设置时间戳。它实现了WritableComparable接口,因此又是可序列化、可进行比较的。(7)CorruptReplicasMap类该类是有关失效块的映射表。如果一个块被认为是失效的,是指该块对应的全部块副本都失效而不可用。CorruptRe
43、plicasMap类定义了一个有序Map映射表来表示,一个块对应的块副本可能在其它DataNode上,corruptReplicasMap表示一个失效的块到对应的全部块副本所在的DataNode集合的映射。(8)UnderReplicatedBlocks类UnderReplicatedBlocks类是描述某些块的副本数量不足块的实体类,而且,对于块设定了优先级,通过一个优先级队列来管理块副本不足的块的集合。权限为0的块,具有最高的优先级,而且,一个块的副本只能有一个具有最高优先级。如果某些块副本数量不足,可以通过该队列来根据块的优先级执行块复制操作,以满足副本因子的要求。如果某个块的副本数量满
44、足副本因子,则需要从队列中删除,更新统计数据。该类提供了想队列中添加和删除块等基本操作。(9)PendingReplicationBlocks类PendingReplicationBlocks类是描述当前尚未完成块副本复制的块的列表。因为HDFS支持块的流水线复制,所以,在执行流水线复制的过程中,因为这种可并行的复制方式使得某些块副本的复制完成时间呈现阶梯状,也就是使用一个数据结构来保存这些尚未复制完成的块副本。而且,该类中还定义了一个内部后台线程类PendingReplicationMonitor,用来监视流水线复制过程中块复制的进度情况。(10)LeaseManager类LeaseMana
45、ger类表示对文件的租约进行管理。很自然地,对于租约的表示与管理,在该类的内部定义了两个内部类:Lease内部类和Monitor内部线程类。Lease内部类:因为文件系统客户端需要向NameNode请求写数据(向NameNode结点写数据块),因此一个文件系统客户端必须持有一个Lease实例,该Lease实例包含文件系统客户端的持有身份(客户端名称)、最后更新Lease时间(用于判断是否超时)、所要写数据的路径(应该与指定的DataNode上文件系统的Path相关)。对于每一个文件系统客户端,都应该持有一个Lease,Lease管理一个客户端的全部锁(写锁),其中Lease中包含的最后更新时间需要文件系统客户端周期地检查来实现更新,这样写数据才不会因为超时而放弃一个Lease。当然,如果一个文件系统客户端发生故障,或者它不需要持有该Lease,也就是不需要执行文件的写操作,那么它会释放由它所持有的Lease管理的全部的锁,以便满足其它客户端的请求。Monitor内部线程类:它是用来周期性地(每2s检查一次)检查LeaseManager管理器所维护的Lease列表中是否有Lease过期的文件系统客户端,如果过期则从Lease列表中删除掉。(11)SafeModelnfo类SafeModelnfo类是FSNamesystem的一个内部类,定义了与安全模式相
限制150内