一、HDFS基础下面是HDFS设计的目标。1.硬件故障硬件故障应该是HDFS的常态而不是例外。HDFS由数百或数千台服务器(计算机)组成,每台服务器都存储文件系统数据的一部分。HDFS存在大量组件并且每个组件都具有非平凡的故障概率这一事实意味着某些组件并非始终正常运行。因此,检测故障并快速、自动地从故障中恢复是HDFS的设计目标。2.流式数据访问在HDFS上运行的应用程序不是通常在通用文件系统上运行并且需要对其数据集进行流式访问的通用应用程序。HDFS用于批处理,而不是供用户交互使用。它更注重数据访问的高吞吐量,而不是数据访问的低延迟。UNIX(POSIX)标准的可移植操作系统接口(PortableOperatingSystemInterfaceofUNIX,POSIX)标准设置的一些硬约束对于HDFS来说是不必要的,因此HDFS会调整一些POSIX特性来提高数据吞吐量,这已经被证明是有效的。3.非常大的数据集HDFS上运行的应用程序具有非常大的数据集。HDFS上的文件大小通常在千兆字节(GB)到太字节(TB)之间。因此,HDFS需要在设计上支持大文件存储,提供整体更高的数据传输带宽,能够在一个集群中扩展到成百上千个节点。一个HDFS实例需要支持数千万个文件。4.简单的一致性模型HDFS应用程序需要一个“一次写入,多次读取”的访问模型。假定文件在创建、写入和关闭后不能更改。这种假设简化了数据一致性问题并实现了高吞吐量数据访问。MapReduce应用程序或网络爬虫应用程序都非常适合此模型。将来,需要扩展此模型以支持对文件的额外写入。5.移动计算而不是移动数据当应用程序在其操作的数据附近执行时,计算效率更高。当数据集很大时尤其如此,它可以最大限度地减少网络拥塞并增加系统的整体吞吐量。HDFS为应用程序提供了一个接口,使它们更接近数据所在的位置。6.跨异构软硬件平台的可移植性HDFS的设计考虑了异构软硬件平台之间的可移植性,有利于HDFS作为大规模数据应用平台的推广。从Hadoop这些年的发展来看,HDFS正是凭借着以上特点,成为了不断演进的大数据系统的坚实基石。2.HDFS架构HDFS是一个典型的主/备(Master/Slave)架构的分布式系统,它由一个名称节点Namenode(Master)+多个数据节点Datanode(Slave)组成。其中,Namenode提供元数据服务,Datanode提供数据流服务,用户通过HDFS客户端与Namenode和Datanode交互访问文件系统。如图3-1所示,HDFS将一个文件的数据分成若干个块(Blocks)。每个块都存储在一组数据节点上。Namenode负责维护文件到Blocks的命名空间映射,以及每个Block到Datanodes的数据块映射。地图。▲图3-1HDFS架构当HDFS客户端对文件系统进行创建、打开、重命名等操作时,Namenode响应请求并更改命名空间,然后返回映射相关数据块的Datanode.客户端按照流协议完成数据读写。HDFS的基本概念HDFS的架构比较简单,但是涉及的概念很多。几个重要的概念如下:1.块(Block)Block是HDFS文件系统处理的最小单位。一个文件可以根据块的大小分成多个块。与Linux文件系统中的数据块不同,HDFS文件通常是非常大的文件,所以块大小一般设置的比较大,默认为128MB。2、副本(Replica)HDFS通过冗余存储保证数据的完整性,即一个block会存储在N个Datanode中,当HDFSclient向Namenode申请新的block时,Namenode会根据该Block分配相应的block到块分配策略Datanodereplica,这些Datanode组成一个管道(pipeline),数据按顺序串行写入,直到块写入完成。3、名称节点(Namenode)Namenode是HDFS文件系统的管理节点。它主要负责维护文件系统的命名空间(Namespace)或文件目录树(Tree)和文件数据块映射(BlockMap),对外提供文件服务。HDFS文件系统遵循POXIS协议标准,类似于Linux文件系统。它采用基于Tree的数据结构,以INode为节点,实现一个目录下的多个子目录和文件。INode是一个抽象类,代表了File/Directory的层级关系。对于一个文件,INodeFile不仅包含基本的文件属性信息,还包含相应的Block信息。数据块映射信息由BlockMap管理。在Datanode的心跳报告中,它会将负责存储的Block列表上报给Namenode。BlockMap负责维护BlockID到Datanode的映射,以便在查找文件时快速找到Block对应的HDFS位置。每个HDFS操作都记录有FSEditLog信息。一旦Namenode崩溃重启,HDFS操作可以从每个FSEditLog恢复,恢复整个文件目录树。如果HDFS集群发生了多次变更,那么整个过程会相当长。因此,HDFS会周期性地将Namenode的元数据以FSImage的形式写入文件中。此操作相当于拍摄HDFS元数据的快照。恢复时,只能恢复FSImage之后的FSEditLog。由于Namenode需要在内存中存储大量信息,恢复过程中集群不可用,HDFS提供HA(主备Namenode实现failover故障转移)和Federation(多组Namenode提供元数据服务,对外以挂载表的形式)提供统一的命名空间)特性,提高稳定性,降低元数据压力。4.DatanodeDatanode是HDFS文件系统的数据节点,提供基于块的本地文件读写服务。定期向Namenode发送心跳。块由本地文件系统中的数据文件和元数据文件组成。前者是数据本身,后者记录的是块长度、校验和(checksum)等信息。在扫描或读取数据文件时,HDFS即使运行在廉价的硬件上,也可以通过多副本的能力来保证数据的一致性。5、文件系统HDFS客户端实现了标准的HadoopFileSystem接口,向上层应用提供了多种文件操作接口,内部使用了DFSClient等对象,封装了更复杂的交互逻辑,这些逻辑对客户端很重要。是透明的。三、HDFS读写流程1、HDFS客户端写入流程图3-2为客户端完成HDFS文件写入的主要流程。▲图3-2客户端完成HDFS写入的主要流程1)创建文件,获取租约。HDFS客户端调用DistributedFileSystem#create远程调用Namenode提供的文件创建操作,Namenode在指定路径下创建一个空文件。文件并为客户端创建一个租约(在续约期间,只有一个客户端可以向文件写入数据),然后将这个操作记录到EditLog(编辑日志)中。Namenode返回相应信息后,客户端会根据这些信息创建一个标准的HadoopFSDataOutputStream输出流对象。2)写入数据HDFS客户端开始向HdfsData-OutputStream写入数据。由于当前没有可写的block,DFSOutputStream针对若干个Datanode向Namenode申请,根据replicas的数量组成pipeline来完成数据的写入,如图3-3所示。▲图3-3流水线数据写入示意图3)串行写入数据,直到区块客户端数据以字节流的形式写入到chunk中(以chunk为单位计算校验和(checksum))。几个chunk组成一个数据包,数据从客户端以数据包的形式发送给第一个Datanode,然后第一个Datanode将数据发送给第二个Datanode并完成本地写入,以此类推,直到最后一个DatanodewritesLocal成功,数据包可以从缓存中移除,如图3-4所示。▲图3-4串口写数据示意图4)重复步骤2、3,然后写数据包和回复数据包,直到所有数据都写完。5)关闭文件并释放租约。客户端关闭文件后,缓存中的数据发送完毕后,HDFS客户端会远程调用Namenode执行文件关闭操作。在定期的心跳上报中,Datanode上报新写入的带有增量信息的Block,Namenode会更新相应的数据块映射,判断数据是否可以被视为Fullydurable(满足最小备份因子)。2.HDFS客户端读取流程相对于HDFS文件写入流程,HDFS读取流程相对简单,如图3-5所示。▲图3-5HDFS读取流程1)HDFS客户端远程调用Namenode,查询元数据信息,获取该文件的数据块位置列表,返回封装了DFSIntputStream的HdfsDataInputStream输入流对象。2)客户端选择一个可用的Datanode服务器,请求建立一个输入流。3)Datanode将原始数据和校验和以数据包的形式写入输入流。4)客户端接收数据。如果遇到异常,则跳到第2步,直到读取完所有数据,然后客户端关闭输入流。客户端在读取时,可能会遇到Datanode或Block异常,导致本次读取失败。由于HDFS的多副本保证,DFSIntputStream会切换到下一个Datanode进行读取。与HDFS写入类似,checksum用于保证读取数据的完整性和准确性。本文节选自《腾讯大数据构建之道》,经发布者授权发布。(书号:978-7-111-71076-9)
