3.1 HDFS的简介
3.1.1 HDFS的演变
HDFS源于Google在2003年10月份发表的**GFS(Google File System)**论文。
传统的文件系统对于数据的处理方式是将数据文件直接存储在一台服务器上。这样会产生两个问题:
- 当数据量越来越大的时候,需要扩容
- 文件很大时,上传下载非常耗时
对于第一个问题,扩容。扩容有两种方式,一是纵向扩容,即增加磁盘和内存;另一种是横向扩容,即增加服务器数量。
分布式文件系统使用的就是横向扩容。
对于第二个问题,传输效率。常规的解决办法是将一个大文件切分成多个数据块,将数据块以并行的方式进行存储。
这里以30G的文本文件为例,将其切分成3块,每块大小1OG(实际上每个数据块都很小,只有100M左右),将其存储在文件系统中,如图3一3所示。
从图3一3可以看出,原先一台服务器要存储30G的文件,此时每台服务器只需要存储10G的数据块就完成了工作,从而解决了上传下载的效率问题。但是文件通过数据块分别存储在服务器集群中,那么如何获取一个完整的文件呢?针对这个问题,就需要再考虑增加一台服务器,专门用来记录文件被切割后的数据块信息以及数据块的存储位置信息,如图3-4所示。
3.1.2 HDFS的基本概念
- NameNode(名称节点、主节点)
NameNode是HDFS集群的主服务器,通常称为名称节点或者主节点。NameNode关闭,就无法访问Hadoop集群。NameNode主要以元数据的形式进行管理和存储,用于维护文件系统名称并管理客户端对文件的访问;NameNode记录对文件系统名称空间或其属性的任何更改操作;HDFS负责整个数据集群的管理,并且在配置文件中可以设置备份数量,这些信息都由NameNode存储. - DataNo(数据节点)
DataNode是HDFS集群中的从服务器,通常称为数据节点。文件系统存储文件的方式是将文件切分成多个数据块,这些数据块实际上是存储在DataNode节点中的,因此DataNode机器需要配置大量磁盘空间。它与NameNode保持不断的通信,DataNode在客户端或者NameNode的调度下,存储并检索数据块,对数据块进行创建、删除等操作,并且定期向NameNode发送所存储的数据块列表,每当DataNode启动时,它将负责把持有的数据块列表发送到NameNode机器中。 - Block(数据块)
每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位,HDFS同样也有块(block)的概念,它是抽象的块,而非整个文件作为存储单元,在Hadoop2.x版本中,默认大小是128M,且备份3份,每个块尽可能地存储于不同的中。按块存储的好处主要是屏蔽了文件的大小(在这种情况下,可以将一个文件分成N个数据块,存储到各个磁盘,就简化了存储系统的设计。为了数据的安全,必须要进行备份,而数据块非常适合数据的备份〕,提供数据的容错性和可用性。 - Rack(机架)
Rack是用来存放部署Hadoop集群服务器的机架,不同机架之间的节点通过交换机通信,HDFS通过机架感知策略(存储策略为本地一份,同机架内其他某一节点上一份,不同机架的某一节点上一份。),使NameNode能够确定每个DataNode所属的机架ID,使用副本存放策略,来改进数据的可靠性、可用性和网络带宽的利用率。 - Metadata(元数据)
元数据从类型上可分为三种信息形式,一是维护HDFS中文件和目录的信息,如文件名、目录名、父目录信息、文件大小、创建时间、修改时间等;二是记录文件内容,存储相关信息,如文件分块情况、副本个数、每个副本所在的DataNode信息等;三是用来记录HDFS中所有DataNode的信息,用于DataNode管理。NameNode中元数据的大小可以显示集群的规模
小提示:具体文件内容不是元数据,元数据是用于描述和组织具体的文件内容,如果没有元数据,具体的文件内容将变得没有意义。元数据的作用十分重要,它们的可用性直接决定了HDFS的可用性。
3.1.3 HDFS的特点
- 优点
- 高容错。
HDFS可以由成百上千台服务器组成,每个服务器存储文件系统数据的一部分。HDFS中的副本机制会自动把数据保存多个副本,DataNode节点周期性地向NameNode发送心跳信号,当网络发生异常,可能导致DataNode与NameNode失去通信,NameNode和DataNode通过心跳检测机制,发现DataNode宕机,DataNode中副本丢失,HDFS则会从其他DataNode上面的副本自动恢复,所以HDFS具有高的容错性。 - 流式数据访问。
HOFS的数据处理规模比较大,应用程序一次需要访问大量的数据,同时这些应用程序一般都是批量地处理数据,而不是用户交互式处理,所以应用程序能以流的形式访问数据集,请求访问整个数据集要比访问一条记录更加高效。 - 支持超大文件。
HDFS具有很大的数据集,旨在可靠的大型集群上存储超大型文件(GB、TB、PB级别的数据),它将每个文件切分成多个小的数据块进行存储,除了最后一个数据块之外的所有数据块大小都相同,块的大小可以在指定的配置文件中进行修改,在Hadoop2.x版本中默认大小是128M。 - 高数据吞吐量。
HDFS采用的是“一次写人,多次读取"这种简单的数据一致性模型,在HDFS中,一个文件一旦经过创建、写人、关闭后,一旦写人就不能进行修改了,只能进行追加,这样保证了数据的一致性,也有利于提高吞叶量。 - 可构建在廉价的机器上。
Hadoop的设计对硬件要求低,无须构建在昂贵的高可用性机器上,因为在HDES设计中充分考虑到了数据的可靠性、安全性和高可用性。
- 高容错。
- 缺点
- 高延迟。
HDFS不适用于低延迟数据访问的场景,例如,毫秒级实时查询。 - 不适合小文件存取场景。
对于Hadoop系统,小文件通常定义为远小于HDFS的数据块大小(128(B)的文件,由于每个文件都会产生各自的元数据(约150字节),Hadoop通过NameNode来存储这些信息,若小文件过多,容易导致NameNode存储出现瓶颈。 - 不适合并发写人。
HDFS目前不支持并发多用户的写操作,写操作只能在文件末尾追加数据。
- 高延迟。
3.2 HDFS 的架构和原理
3.2.1 HDFS 的存储结构
HDFS采用主从架构(Mater/Slave架构)。由一个NameNode(主节点)和多个DataNode(从节点)组成。NameNode管理分布式文件系统的命名空间:在NameNode内部以元数据形式维护着两个文件,分别是FsImage镜像文件和EditLog日志文件。其中FsImage镜像文件用于存储整个文件系统命名空间的信息,EditLog日志文件用于持久记录文件系统元数据的变化。当NameNode启动的时候,EditLog日志文件就会被加载到内存中,然后对内存的数据执行进行记录,以确保所保留的数据处于最新状态。
随着集群运行时间长,NameNode中存储的元数据信息越来越多,这样就会导致EditLog日志文件越来越大。当集群重启时,NameNode需要恢复元数据信息,首先加载上一次的F.slmage镜像文件,然后在重复EditLog日志文件的操作记录,一旦EditLog日志文件很大,在合并的过程中就会花费很长时间,而且如果NameNode宕机就会丢失数据。为了解决这个问题,HDFS中提供了SecondaryNameNode(辅助名称节点),它并不是要取代NameNode也不是NameNode的备份,它的职责主要是周期性地把ameNode中的EditLog日志文件合并到Fslmage镜像文件中,从而减小EditLog日志文件的大小,缩短集群重启时间,并且保证了HDFS系统的完整性。
NameNode存储的是元数据信息,元数据信息并不是真正的数据,真正的数据是存储在DataNode中。DataNode是负责管理它所在节点上的数据存储。DataNode中的数据块是以文件的类型存储在磁盘中,其中包含两个文件,一是数据本身(仅数据),二是每个数据块对应的一个元数据文件(包括数据长度,块数据校验和,以及时间戳)。
3.2.2HDFS 文件读写原理
- HDFS写数据原理
HDFS中的写数据流程可以分为12个步骤,具体如下:- 客户端发起文件上传请求,通过RPC(远程过程调用)与NameNode建立通信。
- NameNode检查元数据文件的系统目录树。
- 若系统目录树的父目录不存在该文件相关信息,返回客户端可以上传文件。
- 客户端请求上传第一个Block数据块,以及数据块副本的数量(可以自定义副本数量,也可以使用集群规划的副本数量)。
- NameNode检测元数据文件中DataNode信息池,找到可用的数据节点(DataNode01,DataNOde02和DataNOde03)。
- 将可用的数据节点的IP地址返回给客户端。
- 客户端请求3台节点中的一台服务器DataNode-01,进行传送数据(本质上是一个RPC调用,建立管道Pipeline)'DataNode_OI收到请求会继续调用服务器DataNode_02,然后服务器DataNode_02调用服务器DataNode03。
- DataNode之间建立Pipeline后,逐个返回建立完毕信息。
- 客户端与IhaNode建立数据传输流,开始发送数据包(数据是以数据包形式进行发送 10. 客户端向DataNode_01上传第一个Block数据块,是以Packet为单位(默认64K)发送数据块。当DataNode时收到一个Packet就会传给DataNode02,DataNode02传给DataNode-03;DataNode-01每传送一个Packet都会放人一个应答队列等待应答。
- 数据被分割成一个个Packet数据包在Pipeline上依次传输,而在Pipeline反方向上,将逐个发送Ack(命令正确应答),最终由Pipeline中第一个DataNode节点DataNode01将Pipeline的Ack信息发送给客户端。
- DataNode返回给客户端,第一个Block块传输完成。客户端则会再次请求NameNode上传第二个Block块和第三个Block块到服务器上,重复上面的步骤,直到3个Bk都上传完毕。
小提示:Hadoop在设计时考虑到数据的安全与高效,数据文件默认在HDFS上存放3份,存储策略为本地一份,同机架内其他某一节点上一份,不同机架的某一节点上一份。
Ack:检验数据完整性信息
- HDFS读数据原理
HDFS中的读数据流程可以分为4个步骤,具体如下:- 客户端向NameNode发起RPC请求,来获取请求文件Block数据块所在的位置。
- NameNode检测元数据文件,会视情况返回Block块信息或者全部Block块信息,对于每个Block块,NameNode都会返回含有该Block副本的DataNode地址。
- 客户端会选取排序靠前的DataNode来依次读取Block块(如果客户端本身就是DataNode,那么将从本地直接获取数据),每一个Block都会进行CheckSum(完整性验证),若文件不完整,则客户端会继续向NameNode获取下一批的Block列表,直到验证读取出来文件是完整的,则Block读取完毕。
- 客户端会把最终读取出来所有的Block块合并成一个完整的最终文件(如1.txt).
小提示:NameNode返回的DataNode地址,会按照集群拓扑结构得出DataNode与客户踹的距离,然后进行排序。排序有两个规则:网络拓扑结构中距离客户端近的则靠前;心跳机制中超时汇报的DataNode状态为无效的,则排靠后。