HDFS 简介 与HDFS 架构
3.1 HDFS 简介
任务目的
任务1:HDFS 的演变
HDFS 源于Google在2003年10月份发表的GFS(Google File System)论文,接下来从传统的文件系统入手,开始学习分布式文件系统,以及分布式文件系统是如何演变而来。
传统的文件系统对海量数据的处理方式是将数据文件直接存储在一台服务器上。如下图所示:
从上图可以看出,传统的文件系统在存储数据时,会遇到两个问题,具体如下:
为了解决传统文件系统遇到的存储瓶颈问题,首先考虑的就是扩容,扩容有两种形式,一种是纵向扩容,即增加磁盘和内存;另一种是横向扩容,即增加服务器数量。通过扩大规模达到分布式存储,这种存储形式就是分布式文件存储的雏形,如下图所示:
解决了分布式文件系统的存储瓶颈问题之后,还需要解决文件上传与下载的效率问题,常规的解决办法是将一个大的文件切分成多个数据块,将数据块以并行的方式进行存储。这里以30G的文本文件为例,将其切分成3块,每块大小10G(实际上每个数据块都很小,只有100M左右),将其存储在文件系统中,如下图所示:
从上图可以看出,原先一台服务器要存储30G的文件,此时每台服务器只需要存储10G的数据块就完成了工作,从而解决了上传下载的效率问题。但是文件通过数据块分别存储在服务器集群中,那么如何获取一个完整的文件呢?
针对这个问题,就需要再考虑增加一台服务器,专门用来记录文件被切割后的数据块信息以及数据块的存储位置信息,如下图所示:
从上图可以看出,文件存储系统中增加了一台服务器D用于管理其他服务器,服务器D记录着文件被切分成多少个数据块,这些数据块分别存储在哪台服务器中,当客户端访问服务器D请求下载数据文件时,就能够通过类似查找目录的方式查找数据了。通过前面的操作,看似解决了所有的问题,但其实还有一个非常关键的问题需要处理,那就是当存储数据块的服务器中突然有一台机器宕机,就无法正常的获取文件了,这个问题被称为单点故障。针对这个问题,可以采用备份的机制解决。如下图所示:
从上图可以看出,每个服务器中都存储两个数据块,进行备份。服务器A存储blk-001和blk-002,服务器B存储blk-002和blk-003,服务器C存储blk-001和blk-003。当服务器B突然宕机,我们还可以通过服务器A和服务器C查询完整的数据块供客户端访问下载。这就形成了简单的HDFS。
这里的服务器D被称为NameNode,它维护着文件系统内所有文件和目录的相关信息,服务器A、B、C被称为DataNode,用于存储数据块。
任务2:HDFS 的基本概念
HDFS(Hadoop Distributed File System)是一个易于扩展的分布式文件系统,运行在成百上千台低成本的机器上。它与现有的分布式文件系统有许多相似之处,都是用来存储数据的系统工具。
首先,它是一个文件系统,用于存储文件,通过统一的命名空间——目录树来定位文件。例如:
hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
hdfs://localhost:9000/soft/hadoop-2.7.7.tar.gz
其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器都有各自清晰的角色定位。
1. NameNode(名称节点)
NameNode 是 HDFS 集群的主服务器,通常称为名称节点或者主节点。一旦NameNode关闭,就无法访问Hadoop集群。
NamNode主要以元数据的形式进行管理和存储,用于维护文件系统名称并管理客户端对文件的访问;
NameNode 记录对文件系统名称空间(namespace)或其属性的任何更改操作;
HDFS 负责整个数据集群的管理,并且在配置文件中可以设置备份数量,这些信息都由 NameNode 存储。
2. DataNode(数据节点)
DataNode是HDFS集群中的从服务器,通常称为数据节点。
文件系统存储文件的方式是将文件切分成多个数据块,这些数据块实际上是存储在DataNode节点中的,因此DataNode机器需要配置大量磁盘空间。
-它与NamNode保持不断的通信,DataNode在客户端或者NameNode的调度下,存储并检索数据块,对数据块进行创建、删除等操作,并且定期向NameNode发送所存储的数据块列表,每当DataNode启动时,它将负责把持有的数据块列表发送到NameNode机器中。
3. Block(数据块)
每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位。
HDFS同样也有块(Block)的概念,在Hadoop2.x版本中,默认一个块的大小是128M,且备份3份,每个块尽可能地存储于不同的DataNode中。
要在HDFS中存储的文件可以划分为多个分块,每个分块可以成为一个独立的存储单元。与本地磁盘不同的是,HDFS中小于一个块大小的文件并不会占据整个HDFS数据块。
按块存储的好处主要有:
(1)一个文件的大小可以大于网络中任意一个磁盘的容量。文件的所有块并不需要存储在同一个磁盘上,因为他们可以利用集群中的任意一个磁盘进行存储。
(2)使用抽象的块,而不是整个文件作为存储单元,可以简化存储管理,使得文件的元数据可以单独管理。
(3)冗余备份。数据块非常适合用于数据备份,进而可以提供数据容错能力和提高可用性。每个块可以有多个备份(默认为三个),分别保存到相互独立的机器上去,这样就可以保证单点故障不会导致数据丢失。
4. Rack(机架)
Rack 是用来存放部署 Hadoop 集群服务器的机架,不同机架之间的节点通过交换机通信,HDFS通过机架感知策略,使NameNode能够确定每个DataNode所属的机架ID,使用副本存放策略,来改进数据的可靠性、可用性和网路带宽的利用率。
** 5.Metadata元数据**
元数据从类型上可分为三种信息形式,分别是:
(1)维护HDFS中文件和目录的信息,如文件名、目录名、父目录信息、文件大小、创建时间、修改时间等;
(2)记录文件内容,存储相关信息,如文件分块情况、副本个数、每个副本所在的DataNode信息等;
(3)用来记录HDFS中所有DataNode的信息,用于DataNode管理。
任务3:HDFS 特点
3.1 HDFS 优点
1. 高容错性
HDFS可以由成百上千服务器组成,每个服务器存储文件系统数据的一部分。
(1)数据自动保存多个副本:HDFS中的副本机制会自动把数据保存多个副本。
(2)副本丢失后,自动恢复 :DataNode节点周期性地向NameNode发送心跳信号,当网络发生异常,可能导致DataNode与NameNode失去通信,NameNode和DataNode通过心跳检测机制,发现DataNode宕机,DataNode中副本丢失,HDFS则会从其他DataNode上面的副本自动恢复,所以HDFS具有较高的容错性。
2. 流式数据访问
HDFS的数据处理规模比较大,应用程序一次需要访问大量的数据,同时这些应用程序一般都是批量地处理数据,而不是用户交互式处理,所以应用程序能以流的形式访问数据集,请求访问整个数据集要比访问一条记录更加高效。
3. 支持超大文件
HDFS具有很大的数据集,旨在可靠地大型集群上存储超大型文件(GB、TB、PB级别的数据),它将每个文件切分成多个小的数据块进行存储,除了最后一个数据块之外的所有数据块大小都相同,块的大小可以在hdfs-site.xml配置文件中进行修改,在Hadoop2.x版本中默认大小是128M。
** 4. 高数据吞吐量**
HDFS采用的是“一次写入,多次读取“这种简单的数据一致性模型,在HDFS中,一个文件一旦经过创建、写入、关闭后,就不能进行修改了,只能进行追加,这样保证了数据的一致性,也有利于提高吞吐量。
5. 可构建在廉价的机器上
Hadoop的设计对硬件要求低,无须构建在昂贵的高可用性机器上,因为在HDFS设计中充分考虑了数据的可靠性、安全性和高可用性。
3.2 HDFS 缺点
1. 高延迟
HDFS不适用于低延迟数据访问的场景,例如,毫秒级实时查询。
2. 不适合小文件存取场景
对于Hadoop系统,小文件通常定义为远小于HDFS的数据块大小(128M)的文件,由于每个文件都会产生各自的元数据,Hadoop通过NameNode来存储这些信息,若小文件过多,容易导致NameNode存储出现瓶颈。
3. 不适合并发写入
HDFS目前不支持并发多用户的写操作,写操作只能在文件末尾追加数据。
3.2 HDFS 架构
任务清单
任务1:HDFS 存储架构图
任务2:HDFS 组成结构
2.1 Client:客户端
在Hadoop生态各组件里,分别有其对应的Client。比如,在HDFS里,在分析其原理时,是HDFS Client。同理,在MapReduce里,是MapReduce Client。
HDFS提供了各种各样的客户端,包括命令行接口、Java API等。Client(代表用户)通过与 NameNode和DataNode 交互访问HDFS中的文件。
Client的主要职责有:
(1)文件切分。文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储。
(2)与 NameNode 交互,获取文件的位置信息。
(3)与 DataNode 交互,读取或者写入数据。
(4)Client 提供一些命令来管理 HDFS,比如启动或者关闭HDFS。
(5)Client 可以通过一些命令来访问 HDFS。
2.2 NameNode :名称节点
NameNode就是 HDFS 的 Master 架构,是一个主管、管理者。其主要职责有:
(1)响应客户端读/写请求;
(2)负责HDFS文件系统的管理工作,具体包括文件Block管理和名称空间(namespace)管理。
-== 文件Block管理(数据块)==
- :Namenode记录着每个文件中各个块所在的数据节点DataNode的位置信息(元数据信息),从NameNode中你可以获得每个文件的每个块所在的DataNode。但是他并不持久化存储这些信息,因为这些信息NameNode会在每次启动系统时动态地重建这些信息。
- 这些元数据信息主要为:、
“文件名 ——> 数据块” 映射
“数据块 ——> DataNode列表” 映射
- 其中,“文件名 ——> 数据块”保存在磁盘上进行持久化存储,需要注意的是NameNode上不保存“数据块——> DataNode列表”映射,该列表是通过DataNode上报给NameNode建立起来的。
- NameNode执行文件系统的名称空间(namespace)操作,例如打开、关闭、重命名文件和目录,同时决定文件数据块到具体DataNode节点的映射。
- 名称空间(namespace)管理:
- 它维护着文件系统树(FileSystem Tree) 以及 文件树中所有的文件和文件夹的元数据(Metadata)。
提问:那么,NameNode是如何管理分布式文件系统的命名空间呢?
其实,在NameNode内部是以元数据的形式,维护着两个文件,分别是FsImage镜像文件和EditLog操作日志文件。这些信息被Cache在RAM中,当然,这两个文件也会被持久化存储在本地硬盘。
其中,FsImage镜像文件用于存储整个文件系统命名空间的信息,EditLog操作日志文件用于持久化记录文件系统元数据发生的变化。
提问:那么,NameNode怎么把元数据保存到磁盘上的呢?
上面这张图片展示了当NameNode启动的时候,FsImage镜像文件就会被加载到内存中,然后对内存里的数据执行记录的操作,以确保内存所保留的数据处于最新的状态,这样就加快了元数据的读取和更新操作。
另外,在NameNode启动后,对文件系统的改动还会被持久化到EditLog中。
只有在NameNode重启时,EditLog才会合并到FsImage文件中,从而得到一个文件系统的最新快照。但是在产品集群中NameNode是很少重启的,这也意味着当NameNode运行了很长时间后,EditLog文件会变得很大。在这种情况下就会出现下面一些问题:
(1)EditLog文件变得越来越大,怎么去管理这个文件是一个挑战。
(2)NameNode的重启会花费很长时间,因为有很多改动(在EditLog中)要合并到FsImage文件上。
(3)如果NameNode宕机了,那我们就丢失了很多改动,因为此时的FsImage文件非常旧。
因此为了克服这个问题,我们需要一个易于管理的机制来帮助我们减小EditLog文件的大小和得到一个最新的FsImage文件,这样也会减小在NameNode上的压力。这跟Windows的恢复点是非常像的,Windows的恢复点机制允许我们对OS进行快照,这样当系统发生问题时,我们能够回滚到最新的一次恢复点上。
现在我们明白了NameNode的功能和所面临的挑战——保持文件系统最新的元数据。
2.3 SecondaryNameNode:检查点节点
为了解决这个问题,HDFS提供了SecondaryNameNode(检查点节点),它并不是要取代NameNode,也不是NameNode的备份,它的职责主要是:
(1)辅助NameNode,分担其工作量;
(2)周期性地把NameNode中的EditLog日志文件合并到FsImage镜像文件中,从而减小EditLog日志文件的大小,缩短集群启动时间,并且保证了HDFS系统的完整性。
(3)在紧急情况下,可辅助恢复NameNode。
上面的图片展示了SecondaryNameNode是怎么工作的?
(1)首先,它定时到NameNode去获取EditLog日志文件,并更新到FsImage(SecondaryNameNode自己的FsImage)上。
(2)一旦它有了新的FsImage文件,它将其拷贝回NameNode中。
(3)NameNode在下次重启时会使用这个新的FsImage文件,从而减少重启的时间。
SecondaryNameNode的整个目的是在HDFS中提供一个检查点。它只是NameNode的一个助手节点。这也是它被认为是检查点节点的原因。
现在,我们明白了SecondaryNameNode所做的不过是在文件系统中设置一个检查点来帮助NameNode更好的工作。它不是要取代掉NameNode也不是NameNode的备份。所以从现在起,让我们养成一个习惯,称呼它为检查点节点吧。
2.4 DataNode :数据节点
DataNode就是HDFS的Slave架构,NameNode下达命令,DataNode执行实际的操作。其主要职责有:
(1)存储整个集群所有数据块;
一个数据块Block会在多个DataNode中进行冗余备份,而一个DataNode对于一个块最多只包含一个备份。所以可以简单地认为DataNode上存储了数据块ID和数据块内容,以及它们的映射关系。
一个HDFS集群可能包含上千个DataNode节点,这些DataNode定时和NameNode进行通信,接受NameNode的指令,为了减轻NameNode的负担,NameNode上并不永久保存哪个DataNode上有哪些数据块的信息,而是通过DataNode启动时的上报来更新NameNode上的映射表。
DataNode和NameNode建立连接后,就会不断地和NameNode保持联系,反馈信息中也包含了NameNode对DataNode的一些命令,如删除数据或者把数据块复制到另一个DataNode。应该注意的是:NameNode不会发起到DataNode的请求,在这个通信过程中,它们严格遵从客户端/服务器架构。
(2)处理数据块的读/写操作。
当然DataNode也作为服务器接受来自客户端的访问,处理数据块读/写请求。==DataNode之间还会相互通信,执行数据块复制任务,==同时,在客户端执行写操作的时候,DataNode之间需要相互配合,以保证写操作的一致性。
DataNode是文件系统Worker中的节点,用来执行具体的任务:存储文件块,被客户端和NameNode调用。同时,它会通过==心跳(Heartbeat)==定时向NameNode发送所存储的文件块信息。
HDFS数据处理原理