大数据技术与应用
上QQ阅读APP看书,第一时间看更新

3.3 HDFS概述

3-3 HDFS

3.3.1 HDFS的概念

1.HDFS介绍

HDFS是基于流数据模式访问和处理超大文件的需求而开发的,是一个分布式文件系统。它是在谷歌的GFS之后出现的另外一种文件系统。它有一定的容错性,且提供了高吞吐量的数据访问,非常适合应用在大规模数据集上。

HDFS的设计特点如下。

1)大数据文件。HDFS非常适合TB及TB以上级别的大文件或大量大数据文件的存储。

2)文件分块存储。HDFS会将一个完整的大文件平均分块存储到不同计算机上,它的意义在于读取文件时可以同时从多台主机读取不同区块的文件,多主机读取比单主机读取效率要高得多。

3)流式数据访问。“一次写入,多次读写”这种模式跟传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化也只能在文件末添加内容。

4)廉价硬件。HDFS可以应用在普通计算机上,这种机制能够让一些公司用几十台廉价的计算机就可以撑起一个大数据集群。

5)硬件故障。HDFS认为所有计算机都可能会出问题,为了防止某台主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其他某几台主机上,如果其中一台主机失效,可以迅速找另一块副本取文件。

2.HDFS优缺点

基于上述的设计特点,HDFS存在一系列的优点及缺陷。

HDFS的优点如下。

1)处理超大文件。这里的超大文件通常是指数百兆字节大小的文件。但是,目前在实际应用中,HDFS已经能用来存储管理PB级的数据了。在雅虎,Hadoop集群已经扩展到了4000个节点。

2)流式数据访问。HDFS的设计建立在“一次写入,多次读写”任务的基础上。这意味着一个数据集一旦由数据源生成,就会被复制并分发到不同的存储节点中,然后响应各种各样的数据分析任务请求。在多数情况下,分析任务都会涉及数据集中的大部分数据,也就是说,对HDFS来说,请求读取整个数据集要比读取一条记录更加高效。

3)运行于廉价的商用机器集群上。Hadoop设计对应急需求比较低,只须运行在低廉的商用硬件集群上,而无须运行在昂贵的高可用性机器上。廉价的商用机也就意味着大型集群中出现节点故障情况的概率非常高。HDFS被设计成遇到上述故障时仍能够继续运行且不让用户察觉到明显的中断。

正是出于以上种种考虑,人们发现,现在HDFS在处理一些特定问题时不但没有优势,反而存在很多局限性,它的局限性及应对策略如下。

1)不适合低延迟数据访问。如果要处理一些用户要求时间比较短的低延迟应用请求,则HDFS不适合。HDFS是为了处理大型数据集分析任务的,主要是为达到高的数据吞吐量而设计的,这就可能要求以高延迟作为代价。

改进策略为:对于那些有低延迟要求的应用程序,HBase是一个更好的选择,通过上层数据管理项目尽可能地弥补这个不足。它在性能上有了很大的提升,它的口号是goes real time(实时运行)。使用缓存或多个Master设计可以降低客户端的数据请求压力,以减少延迟。

2)无法高效存储大量的小文件。小文件是指文件大小小于HDFS上块(block)大小的文件。这样的文件会给Hadoop的扩展性和性能带来严重问题。当Hadoop处理很多小文件时,由于FileInputFormat不会对小文件进行划分,因此每一个小文件都会被当成一个切片(Split)并分配一个映射(Map)任务,导致效率低下。

例如,一个1GB的文件,会被划分成16个64MB的切片,并分配16个映射任务处理,而10000个100KB的文件会被10000个映射任务处理。

改进策略为:要想让HDFS能处理好小文件有不少方法。利用SequenceFile、MapFile、Har等方式归档小文件,这个方法的原理就是把小文件归档起来管理,HBase就是基于此的。

3)不支持多用户写入及任意修改文件。在HDFS的一个文件中只有一个写入者,且写操作只能在文件末尾完成,即只能执行追加操作。目前HDFS还不支持多个用户对同一文件的写操作,及在文件任意位置进行修改。

3.HDFS构成

HDFS的关键元素包含Block、NameNode和DataNode。

● Block:将一个文件进行分块,通常一个块的大小是64MB。

● NameNode:保存整个文件系统的目录信息、文件信息及分块信息,由唯一一台主机专门保存。当然,如果这台主机出错,NameNode就失效了。从Hadoop 2.x开始支持activity-standy模式,即如果主NameNode失效,启动备用主机运行NameNode。

● DataNode:分布在廉价的计算机上,用于存储块文件。

一个完整的HDFS运行在一些节点之上,这些节点运行着不同类型的守护进程,如NameNode、DataNode、Secondary NameNode等,不同类型的节点相互配合,相互协作,在集群中扮演了不同的角色,一起构成了HDFS。

如图3-6所示,在一个典型的HDFS集群中,有一个NameNode、一个Secondary NameNode和至少一个DataNode,而HDFS客户端数量没有限制。所有的数据均存放在运行DataNode进程的节点的块里。

图3-6 HDFS架构

1)HDFS客户端(HDFS Client)。HDFS客户端是指用户和HDFS交互的手段,HDFS提供了非常多的客户端,包括命令行接口、Java API、Thrift接口、C语言库、用户空间文件系统等。

2)元数据节点NameNode。NameNode是管理者,一个Hadoop集群只有一个NameNode节点,是一个通常在HDFS实例中的单独机器上运行的软件。NameNode主要负责HDFS文件系统的管理工作,具体包括命名空间(NameSpace)管理和文件块管理。NameNode决定是否将文件映射到DataNode的复制块上。对于最常见的3个复制块,第一个复制块存储在同一个机架的不同节点上,最后一个复制块存储在不同机架的某个节点上。

NameNode是HDFS的大脑,它维护着整个文件系统的目录树,以及目录树里所有的文件和目录。这些信息以两种文件形式存储在本地文件中:一种是命名空间镜像,也称为文件系统镜像(File System Image, FSImage),即HDFS元数据的完整快照,每次NameNode启动时,默认会加载最新的命名空间镜像;另一种是命名空间镜像的编辑日志(Edit Log)。

3)第二名称节点Secondary NameNode。第二名称节点是用于定期合并命名空间镜像和命名空间镜像的编辑日志的辅助守护进程。每个HDFS集群都有一个SecondaryNameNode,在生产环境下,一般Secondary NameNode也会单独运行在一台服务器上。

FSImage文件其实是文件系统元数据的一个永久性检查点,但并非每一个写操作都会更新这个文件,因为FSImage是一个大型文件,如果频繁地执行写操作,会使系统运行极为缓慢。解决方案是NameNode只改动内容预写日志,即写入命名空间镜像的编辑日志。随着时间的推移,编辑日志会变得越来越大,那么一旦发生故障,将会花费非常多的时间来回滚操作,所以就像传统的关系型数据库一样,需要定期地合并FSImage和编辑日志。如果由NameNode来进行合并操作,那么NameNode在为集群提供服务时可能无法提供足够的资源。为了彻底解决这一问题,Secondary NameNode应运而生。NameNode和Secondary NameNode的交互如图3-7所示。

图3-7 NameNode与Secondary NameNode的交互

① Secondary NameNode引导NameNode滚动更新编辑日志文件,并开始将新的内容写入Edit Log.new。

② Secondary NameNode将NameNode的FSImage和编辑日志文件复制到本地的检查点目录。

③ Secondary NameNode载入FSImage文件,回放编辑日志,将其合并到FSImage,将新的FSImage文件压缩后写入磁盘。

④ Secondary NameNode将新的FSImage文件送回NameNode, NameNode在接收新的FSImage后直接加载和应用该文件。

⑤ NameNode将Edit Log.new更名为EditLog。

默认情况下,该过程每小时发生一次,或者当NameNode的编辑日志文件达到默认的64MB时也会被触发。

注意:从名称上来看,初学者会以为当NameNode出现故障时,Secondary NameNode会自动成为新的NameNode,也就是NameNode的“热备”,这是错误的。

4)DataNode是HDFS的主从架构中从角色的扮演者,它在NameNode的指导下完成I/O任务。如前文所述,存放在HDFS中的文件都是由HDFS的块组成的,所有的块都存放于DataNode。实际上,对于DataNode所在的节点来说,块就是一个普通的文件,可以去DataNode存放块的目录下(默认路径是$(dfs.data.dir)/current)查看,块的文件名为blk.blkID。

DataNode会不断地向NameNode报告。初始化时,每个DataNode将当前存储的块告知NameNode,在集群正常工作时,DataNode仍会不断地更新NameNode,为其提供本地修改的相关信息,同时接收来自NameNode的指令,创建、移动或删除本地磁盘上的数据块。

5)块。每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位,而文件系统也有文件块的概念,如ext3、ext2等。文件系统的块大小只能是磁盘块大小的整数倍,磁盘块的大小一般是512字节,文件系统的块大小一般为几千字节,如ext3的文件块大小为4096字节,Windows的文件块大小为4096字节。用户在使用文件系统对文件进行读取或写入时,完全不知道块的细节,这些对于用户是透明的。

HDFS同样也有块的概念,但是HDFS的块比一般文件系统的块大得多,默认为64MB,并可以随着实际需要而变化,配置项为hdfs-site.xml文件中的dfs.block.size项。与单一文件系统相似,HDFS上的文件也被划分为块大小的多个分块,它是HDFS存储处理的最小单元。

例如,某个文件data.txt大小为150MB,如果此时HDFS的块大小没有经过配置,则默认为64MB,该文件在HDFS中的存储情况如图3-8所示。图3-8中,圆形为保存该文件的第一个块,大小为64MB;方形为保存文件的第二个块,大小为64MB;五边形为保存文件的第三个块,大小为22MB。与其他文件系统不同的是,HDFS小于一个块大小的文件不会占据整个块的空间,所以第三个块的大小为22MB,而不是64MB。

HDFS中的块如此大是为了最小化寻址开销。如果块设置得足够大,从磁盘传输数据的时间可以明显大于定位这个块开始位置所需的时间。这样传输一个由多个块组成的文件的时间取决于磁盘传输的效率。得益于磁盘传输速率的提升,块的大小可以被设置为128MB甚至更大。

在hdfs-site.xml文件中,还有一个配置项为dfs.relication。该配置项为每个HDFS的块在Hadoop集群中保存的份数,值越高,冗余性越好,占用存储也越多,默认为3,即有2份冗余。如果设置为2,那么该文件在HDFS中的存储情况如图3-9所示。

图3-8 HDFS中的块(默认大小)

图3-9 HDFS中的块(2份冗余)

使用块的优点如下。

① 可以保存比存储节点单一磁盘大的文件。块的设计实际上就是对文件进行分片,分片可以保存在集群的任意节点,从而使文件存储跨越了磁盘甚至机器的限制,如data.txt文件被切为3个块,并存放于3个DataNode之中。

② 简化存储子系统。将存储子系统控制单元设置为块,可简化存储管理,并且实现了元数据和数据的分开管理和存储。

③ 容错性高。这是块非常重要的一个优点。如果将dfs.relication设置为2,那么任意一个块损坏,都不会影响数据的完整性,用户在读取文件时,不会察觉到异常。之后集群会将损坏的块的副本从其他候选节点复制到集群中能正常工作的节点,从而使副本数回到配置的水平。

3.3.2 HDFS的操作

1.HDFS常用命令

Hadoop自带一组命令行工具,其中有关HDFS的命令是其工具集的一个子集。命令行工具虽然是最基础的文件操作方式,却是最常用的。作为一名合格的Hadoop开发人员和运维人员,熟练掌握命令行工具是非常有必要的。

执行“hadoop dfs”命令可以显示HDFS常用命令的使用信息,如下所示。

下面详细介绍上述命令行接口,并用例子说明各自的功能,如表3-1所示。

表3-1 HDFS常用命令及其功能

(续)

2.HDFS命令操作简单示例

文件系统已经就绪,可以执行所有其他文件系统都有的操作,如读取文件、创建目录、移动文件、删除数据、列出索引目录等。执行“hadoop fs-help”命令,即可看到所有命令的详细帮助文件。

首先从本地文件系统将一个文件复制到HDFS。

该命令调用Hadoop文件系统的shell命令fs,该命令提供了一系列子命令。在本例中执行的是-copyFromLocal,本地文件test.txt被复制到运行在localhost上的HDFS实例中,路径为user/tom/test.txt。事实上,可以省略主机的URI默认设置(即省略“hdfs://localhost”),因为该项已在“core-sile.xml”中指定。

也可以使用相对路径,并将文件复制到HDFS的home目录中,在本例中为“/user/tom”。

把文件复制回本地文件系统,并检查是否一致。

由于MD5键值相同,因此这个文件在HDFS之旅中得以幸存并保存完整。

3.HDFS中的文件访问权限

针对文件和目录,HDFS有与POSIX非常相似的权限模式。

HDFS提供三类权限模式:只读权限(r)、写入权限(w)和可执行权限(x)。读取文件或列出目录内容时需要只读权限。写入一个文件或在一个目录上创建及删除文件或目录,需要写入权限。对于文件而言,可执行权限可以忽略,因为不能在HDFS中执行文件(与POSIX不同),但在访问一个目录的子项时需要该权限。对目录而言,当列出目录内容时需要只读权限,当新建或删除子文件或子目录时需要写入权限,当访问目录的子节点时需要可执行权限。

每个文件和目录都有所属用户(owner)、所属组别(group)及模式(mode)。这个模式是由所属用户的权限、组内成员权限及其他用户的权限组成的。

默认情况下,可以通过正在运行进程的用户名和组名来唯一确定客户端的标识。但由于客户端是远程的,任何用户都可以简单地在远程系统上以他的名义创建一个账户来进行访问。因此,作为共享文件系统资源和防止数据意外损失的一种机制,权限只能供合作团体中的用户使用,而不能在一个不友好的环境中保护资源。注意,最新版的Hadoop已经支持Kerberos用户认证,该认证去除了这些限制。但是,除了上述限制以外,为防止用户或自动工具及程序意外修改或删除文件系统的重要部分,启用权限控制还是很重要的。

如果启用权限检查,就会检查所属用户权限,以确认客户端的用户名与所属用户是否匹配,同时检查所属组别权限,以确认该客户端是否是该用户组的成员;若不符,则检查其他权限。

注意,这里有一个超级用户(super-user)的概念,超级用户是NameNode进程的标识。宽泛地讲,如果用户启动了NameNode,那他就是超级用户。另外,管理员可以用配置参数指定一组特定的用户,如果对组进行了超级用户的设置,那么这个组的成员也会是超级用户。对于超级用户,系统不会执行任何权限检查。