学习目标

● 了解文件系统的分类,能够描述不同文件系统的特点。
● 掌握HDFS架构,能够描述HDFS架构的主要组件及其作用。
● 了解HDFS的特点,能够简述HDFS的特点。
● 掌握HDFS的文件读写流程,能够叙述HDFS读写文件的流程。
● 熟悉HDFS的健壮性,能够叙述HDFS心跳机制、副本机制和负载均衡等策略。
● 掌握HDFS的Shel 
操作,能够灵活运用HDFSShel 
命令操作HDFS 。
● 掌握HDFS的JavaAPI操作,能够灵活使用JavaAPI编写的应用程序操作HDFS 。
● 熟悉Federation机制,能够描述Federation机制的结构、特点,并实现Federation机制。
● 了解ErasureCoding,能够简述ErasureCoding节省存储空间的原理。
HDFS(HadoopDistributedFileSystem,Hadoop分布式文件系统)是Hadoop体系中的
重要组成部分,主要用于解决海量数据的文件存储问题,它是目前应用最广泛的分布式文件系
统。本章将从文件系统(FileSystem)的分类开始,带领读者学习HDFS的相关内容及常见
操作。

3.文件系统的分类
1 

在计算机中,文件系统是命名文件及放置文件的逻辑存储和恢复的系统,人们熟悉的
Windows、macOS和Linux操作系统都有文件系统。常见的文件系统分为单机文件系统、网
络文件系统和分布式文件系统。

1.单机文件系统
单机文件系统是所有文件系统的基础,也是常用的一种文件系统,它通过单台计算机的本
地磁盘存储文件,依靠操作系统提供的文件系统实现文件的存储和管理。不过随着互联网的
兴起,数据对存储容量的要求越来越高,单机文件系统的缺点逐渐显现。

● 本地磁盘的存储容量很容易达到存储极限。
● 大量并发的读写操作导致读写性能较低。
● 一旦计算机宕机或者损坏,存储的文件将无法访问甚至丢失,存储可靠性低。
2.网络文件系统
网络文件系统(NetworkFileSystem,NFS)可以看作单机文件系统的网络抽象,其本质
与单机文件系统相似,只不过网络文件系统可以通过网络共享文件,用户可以像访问本地磁盘


第3章HDFS 分布式文件系统53 

上的文件一样便捷地访问远端计算机的文件。网络文件系统的出现在一定程度上解决了单机
文件系统存储容量的问题,这是因为用户可以将文件存储在网络文件系统和本地文件系统两
个位置。但是,网络文件系统没有解决单机文件系统性能低、可靠性低的问题。

3. 
分布式文件系统
分布式文件系统是指多台服务器组成一个集群,通过相互通信的方式将集群内的所有存
储空间资源整合,并对外提供文件访问服务。

在分布式文件系统中,为了解决文件存储的瓶颈问题,可以通过增加服务器数量的方式扩
大存储空间,以此提供大型数据文件所需的存储空间,可扩展性高。

虽然文件存储的瓶颈得以解决,但是面对大量文件的读写请求,如果不能解决读写性能低
的瓶颈,还是无法解决单机文件系统和网络文件系统存在的问题,那么在分布式文件系统中, 
针对读写性能方面的问题是如何解决的呢? 

考虑到单台服务器的存储容量有限,分
布式文件系统在存储一个大文件时,会将其
分成几个相对较小的文件,然后将这些相对
较小的文件存储在分布式文件系统的不同
服务器中。例如,有一个30GB 的1.t文

tx
件,这个文件可以均分成3份,分别存储在3 
台不同的服务器中,每台服务器存储的文件
大小都是10GB,如图3-1所示。

图3-1展示的是服务器B、服务器C和
服务器D联合存储大小为30GB 的1.txt文
件。当读取1.x会先从服务器B、

tt文件时, 
服务器C和服务器D中读取文件1、文件2和文件3, tt。这样做

然后将这3个文件整合为1.x
的好处是可以充分利用集群中不同服务器的资源处理单个文件,从而提高读写性能。
为了记录大文件切分后的信息,还需要一台服务器A,专门用来记录文件被分成几份后的
信息以及存储的位置信息,如图3-2所示。

图3-11.txt文件存储在不同的服务器
图3-
2 
服务器A记录文件的切分信息及存储位置信息

在图3-2中,服务器A记录着文件被分成多少个文件和文件的存储位置。当客户端访问
服务器A请求文件1.t时,服务器A会按照类似查找目录的方式找到对应文件。

tx


54 
Hadoop大数据技术原理与应用(第2版) 

解决了文件存储瓶颈的问题后,其实还有一个关键问题需要处理,就是文件存储的可靠
性。大文件分成小文件存储在不同的服务器上,如果某个服务器突然宕机,就会导致获取的文
件不完整,也就是在单机文件系统和网络文件系统中存在的存储可靠性低的问题。针对这个
问题,分布式文件系统的存储采用了副本机制,该机制通过保存多个副本提高了分布式文件系
统的可靠性。

例如,分布式文件系统设置的副本数为2,那么切分后的每个小文件都会有两份,并且存
储在不同的服务器中,如图3-3所示。


图3-
3 
分布式文件系统的副本存储

在图3-3中,服务器B存储着文件1和文件3,服务器C存储着文件2和文件1,服务器D 
存储着文件2和文件3。如果服务器C突然宕机,那么服务器C上存储的文件1和文件2同
样可以从服务器B和服务器D中获取。分布式文件系统的副本机制极大地提高了文件存储
的可靠性。

2 
HDFS简介

3.
HDFS源于2003年10月发表的论文TheGogleFileSystm,该论文描述了Google开
发的一个产品框架,该框架称为GFS(GoogleFileSystem,Google(e) 文件系统)。Nutch开发人
员借鉴GFS进行开源版本的实现,最终设计了一款类似于GFS的分布式文件系统HDFS 。
本节将针对HDFS架构及其特点进行详细讲解。

3.1 
HDFS架构
2.
HDFS采用的是主从(Master/Slave)架构,即一个HDFS通常是由一个Master和多个
Slave组成,其中,Master在HDFS中扮演的角色为NameNode,主要用于管理HDFS 。Salve 
在HDFS中扮演的角色为DataNode,主要用于存储文件。除此之外,HDFS为了缓解单个
NameNode的压力,还提供了一个SecondaryNameNode,用于辅助NameNode。接下来通过
一张图详细介绍HDFS的架构,如图3-4所示。

1.Blck 

Block是(o) HDFS文件系统中最小的存储单位,通常称为数据块。在HDFS文件系统中存


第3章HDFS 分布式文件系统55 


图3-
4 
HDFS 
架构

储的文件会被拆分成多个Block,每个Block作为独立的单元进行存储,同一文件的多个Block 
通常存放在不同的DaaNodop3.Blc

te。在Hadox版本中,ok的默认大小是128MB 。

需要注意的是,如果文件太小或者文件拆分后的Block没有达到128MB,则Block的大小
也会根据实际情况进行调整,例如,存储在HDFS 文件系统的一个300MB 文件如果拆分为3 
个Block,那么这3个Block的大小分别为128MB 、128MB 和44MB 。

2.MetaDta 

MetaData用(a) 于记录HDFS 文件系统的相关信息,这些信息称为元数据,元数据的内容包
括文件系统的目录结构、文件名、文件路径、文件大小、文件副本数、文件与Block的映射关系, 
以及Block与DataNode的映射关系等信息。

在HDFS 文件系统中,为了确保元数据的快速访问,元数据会保存在内存中。同时,为了
防止元数据丢失,会在本地磁盘生成Fsimage文件以备份元数据。当部署的Hadoop集群初
次启动前进行格式化HDFS 操作时,会在本地磁盘的指定目录生成一个Fsimage文件,启动
Hadoop集群时,NameNode会将Fsimage文件加载到内存中。

Hadoop集群运行的过程中,用户频繁操作HDFS 文件系统,内存中的元数据变化会非常
快。内存中的元数据一旦更新,本地磁盘的Fsimage文件就会同步更新,这些操作非常消耗
NameNode资源。但是,如果不更新本地磁盘的Fsimage文件,就会使内存和本地磁盘存储的
元数据不一致。另外,一旦NameNode宕机,就会丢失元数据。

为了解决上述问题,HDFS 文件系统引入了Edits文件,该文件以追加的方式记录内存中
元数据的每一次变化,这样,如果NameNode宕机,那么可以通过合并Fsimage文件和Edits 
文件的方式恢复内存中存储的元数据。需要注意的是,为了避免Edits文件过大,NameNode 
会定期将Fsimage文件和Edits文件进行合并。

3.NameNd

NameNode(o) 是(e) HDFS 集群的名称结点,通常称为主结点。如果NameNode由于故障原因
而无法使用,那么用户就无法访问HDFS 。也就是说,NameNode作为HDFS 的主结点,起着
至关重要的作用。

NameNode的主要功能如下。

● 管理文件系统的命名空间(NameSpace), 例如打开文件、删除文件、重命名文件、创建目

56 
Hadoop大数据技术原理与应用(第2版) 

录等。

● 处理客户端对文件的读写请求。
● 维护HDFS 的元数据。
● 维护和管理DataNode,并协调DataNode为客户端发起的读写请求提供服务。
4.DataNHDFS 集群中的数据结点,通常称为从结点,其主要功能如下。d是(e) 
DataNode(o) 

● 存储Block。
● 根据NameNode的指令对Block进行创建、复制、删除等操作。
● 定期向NameNode汇报自身存储的Block列表及健康状态。
● 负责为客户端发起的读写请求提供服务。
5.SecodyNNode 

Secondary(n) Na(a) meN(a) od(e) (m) (r) e是HDFS 集群中的辅助结点,它可以定期从NameNode复制
Fsimage文件及合并Edits文件,并将合并结果发送给NameNode,从而辅助NameNode合并
Fsimage文件和Edits文件,减轻NameNode的工作压力。与此同时,由于SecondaryNameNode和
NameNode保存的Fsimage和Edits文件相同,因此它可以作为NameNode的冷备份,即当
NameNode无法使用时,可以通过获取SecondaryNameNode中保存的Fsimage和Edits文件
恢复NameNode的数据和运行状态。

3.2 
HDFS 
的特点
2.
HDFS 是应用最广泛的分布式文件系统,它的特点具体如下。

1. 
存储大文件
HDFS 支持GB 级别甚至TB 级别的文件存储,每个文件都会被切分为多个Block存储在集
群的不同DataNode结点,使得对大型文件进行读写操作时可以采用并行的方式提高吞吐量。

2. 
高容错性
HDFS 的副本机制会为DataNode中的每个Block创建多个副本,这样,即使某个
DataNode宕机,也不会造成数据丢失,这是因为HDFS 可以从保存Block副本的其他
DataNode中读取相同的Block。

3. 
简单的一致性模型
HDFS 采用的是一次写入、多次读取的文件访问模型。在HDFS 中,一个文件经过创建、
写入和关闭后,只能追加,不能修改,并且不支持并发多用户的写操作,这样可以有效保证数据
的一致性。

4. 
移动计算比移动数据更经济
如果应用请求的计算在其操作的数据附近执行,那么该应用的效率要高很多。在数据达
到海量级别时更是如此,这样可以最大限度地减少网络阻塞,并增加系统的整体吞吐量。应用
运行时,将计算迁移到更靠近数据所在的位置通常比将数据迁移到计算所在的位置更好。
HDFS 为应用提供了接口,以使自己更靠近数据所在的位置。

5. 
可移植性
HDFS 可以轻松地从一个平台移植到另一个平台,这有助于广泛应用HDFS 作为大量应
用程序的首选平台。


第3章HDFS 分布式文件系统57 

3 
HDFS 
的文件读写流程

3.
通过对HDFS 架构的学习,读者已经了解HDFS 主要由NameNode和DataNode组成, 
那么它们是如何协作处理HDFS 文件的读写请求的呢? 接下来针对HDFS 文件的读写流程
进行详细介绍。

1.HDFS 
写文件流程
客户端向HDFS 中写文件的具体流程如图3-5所示。


图3-
5 
HDFS 
写文件的具体流程

下面以300MB 大小的1.x针对图3-5所示的HDFS 写文件流程进行介绍。

tt文件为例
,
Client) tx


(1)客户端(上传1.t文件到指定目录的请求,与NameNode建立通信。
(2)NameNode检查客户端是否有上传文件的权限,以及文件是否存在。若通过检查,则
通知客户端上传文件,并向其发送分块策略。
txoc

(3)客户端根据分块策略(以默认128MB 为例)对文件1.t进行切分,形成3个Blk, 
分别是blk1 、blk2 和blk3 。
(4)客户端向NameNode请求上传第一个Block,即blk1 。
(5)NameNode根据副本机制和机架感知向客户端返回可上传blk1 的DataNode列表, 
这里指的是Hadoop1、Hadoop2和Hadoop3。

(6)客户端从NameNode接收到blk1 上传的DataNode列表之后,首先根据就近原则从
DataNode列表中选择一台DataNode(如Hadoop1)并与之建立管道(Pipeline), 用于传输数
据,然后Hadoop1会与第二台DataNode(如Hadoop2)建立管道,最后Hadoop2会与第三台
DataNode(如Hadoop3)建立管道。
(7)首先,Hadoop3向Hadoop2汇报管道建立成功;然后,Hadoop2向Hadoop1汇报管
道建立成功;最后,Hadoop1向客户端汇报管道建立成功,此时客户端与所有DataNode列表
中的所有DataNode都建立了管道。
(8)客户端开始传输blk1,传输过程以流式写入的方式实现,具体过程如下。
①将blk1 写入内存进行缓存。
②将blk1 按照packet(默认为64KB)为单位进行划分。
③将第一个packet通过管道发送给Hadoop1。

58 
Hadoop大数据技术原理与应用(第2版) 

④Hadoop1接收第一个packet之后,客户端会将第二个packet发送给Hadoop1,同时
Hadoop1通过Pipeline将第一个packet发送给Hadoop2。
⑤Hadoop2接收第一个packet之后,Hadoop1会将第二个packet发送给Hadoop2,同时
Hadoop2通过Pipeline将第一个packet发送给Hadoop3。

⑥以此类推,直至blk1 上传完成。
(9)首先,Hadoop3向Hadoop2发送blk1 写入完成的信息;然后,Hadoop2向Hadoop1 
发送blk1 写入完成的信息;最后,Hadoop1向客户端发送blk1 写入完成的信息。
客户端成功上传bk1 后,重复第(的流程,依次上传bk2 和b最终完成1.
文件的上传。
l4)~(9) llk3, txt 

2.HDFS 
读文件流程
客户端从HDFS 中读文件的流程如图3-6所示。


图3-
6 
HDFS 
读文件流程

下面以300MB 大小的1.x针对图3-6所示的HDFS 读文件流程进行介绍。

tt文件为例, 
tx

(1)客户端发起读取1.t文件的请求,与NameNode建立通信。
(2)NameNode检查客户端是否有读取文件的权限,以及文件是否存在。若通过检查,则
通知客户端读取文件,并向其发送1.t文件的Blk列表,该列表中记录了每个Blk及其

txococ
副本所在DataNode的地址,例如Hadoop1、Hadoop2和Hadoop3的主机地址。

(3)客户端按照就近原则从NameNode返回的Block列表读取Block。首先客户端从
Block列表中选择距离自身最近的DataNode(如Hadoop1)读取Block,如果该DataNode可
以读取文件的所有Block,则结束读取;如果该DataNode没有读取文件的所有Block,则客户
端从Block列表中继续选择距离自身最近的DataNode读取剩余的Block,直至获取文件的所
有Block才结束读取。
octx

(4)客户端将读取的所有Blk按照顺序进行合并,最终形成1.t文件。需要注意的
是,如果文件过大,导致NameNode无法一次性读取所有Block,则会分批次将Block列表返
回客户端。

第3章HDFS 分布式文件系统59 

4 
HDFS 
的健壮性

3.
负责、敬业的精神和态度对于保证各行各业的稳定和发展具有重要意义。犹如HDFS 的
主要目标是在出现故障的情况下可靠地存储数据,其运用了心跳机制、副本机制、数据完整性
校验、安全模式和快照5种策略保证存储数据的可靠性,关于这5种策略的具体介绍如下。

1. 
心跳机制
HDFS 在运行期间,为了确保NameNode可以实时获取每个DataNode的健康状态,会在
NameNode和每个DataNode之间建立一种心跳机制,即每个DataNode会根据固定间隔时间
(默认为3s)周期性地向NameNode发送心跳信息。如果NameNode在固定间隔时间内接收
到DataNode发送的心跳信息,则认为该DataNode处于存活状态,否则认为该DataNode处于
假死状态。不过,此时NameNode暂时还不会标注该DataNode处于宕机状态,如果在最大间
隔时间(默认是10min)内仍然没有接收到处于假死状态的DataNode发送的心跳信息,那么此
时NameNode会认为该DataNode处于宕机状态。当某个DataNode处于宕机状态后,可能会
造成某些Block的副本数无法达到系统要求,这时NameNode会启动复制操作,令其他处于
存活状态的DataNode为这些Block创建新的副本。

2. 
副本机制
副本机制可以确保存储在DataNode的每个Block都存在多个副本,默认的副本数为3 
(包含自身), 即每个Block除自身外还存在2个副本,并且每个副本会分配到不同的
DataNode。若其中一台DataNode宕机而导致Block的副本数不足3,HDFS 会为该Block创建
新的副本,并将其存储到处于存活状态的DataNode中,以确保每个Block的副本数为3。

3. 
数据完整性校验
客户端从某个DataNode获取的Block有可能是已损坏的,损坏的原因可能是由于
Datanode的存储设备错误或者网络错误造成的,针对这一问题,HDFS 的客户端实现了对文
件内容进行校验和检查的功能。当客户端从HDFS 读取文件时,会计算这个文件中每个
Block的校验和(Checksum), 并将校验和作为一个单独的隐藏文件保存在HDFS 中。当客户
端获取文件内容后,它会校验从DataNode获取Block的校验和,并与保存为隐藏文件的校验
和进行匹配,如果不匹配,客户端可以选择从其他DataNode中获取该文件的Block。

4. 
安全模式
HDFS 的安全模式是一种特殊状态,该状态下,客户端只能对HDFS 读,不能写。HDFS 
的安全模式分为两种情况,一种情况是HDFS 启动时进入安全模式,此时DataNode会向
NameNode报告自身的Block状态,当Block的副本数符合HDFS 规定的副本数时,该Block 
的数据被认为是完整的,HDFS 会退出安全模式;另一种情况是HDFS 中某个Block的副本丢
失,HDFS 也会进入安全模式,此时NameNode会自动复制Block到DataNode上,当Block的
副本数满足HDFS 规定的副本数时,HDFS 会退出安全模式。

5. 
快照
快照是HDFS 整个文件系统或某个目录在某个时间点的镜像。当用户因错误操作导致
HDFS 中的数据缺失时,可以利用快照恢复缺失数据,使缺失数据的HDFS 恢复至已知的良
好时间点。


Hadoop大数据技术原理与应用(第60 2版) 
3.5 HDFS的Shell操作
3.5.1 HDFSShell介绍 
HDFSShell类似于Linux操作系统中的Shell,是一种命令语言,可以对HDFS上的文件
和目录进行一系列操作。
HDFSShell的语法格式如下。 
hdfs [OPTIONS]SUBCOMMAND [SUBCOMMAND OPTIONS] 
上述语法格式中,各参数的介绍具体如下。
● OPTIONS:可选参数,用来调试Hadoop。例如关闭HDFS或YARN 集群的某个服
务、启动HDFS或YARN 集群的某个服务、指定Hadoop配置文件所在目录等。
● SUBCOMMAND:表示HDFSShell的子命令,用于操作HDFS。根据操作类型的不
同,HDFSShell提供了3种类型的子命令,分别是管理员命令(AdminCommands)、客
户端命令(ClientCommands)和进程命令(DaemonCommands)。其中,管理员命令主
要用于管理员调试HDFS、对HDFS进行加密和配置HDFS的缓存等;客户端命令主
要用于操作人员查看HDFS版本信息和对HDFS文件进行操作等;进程命令主要用于
操作人员启动HDFS集群的指定服务。
● SUBCOMMAND OPTIONS:表示HDFSShell子命令的选项。例如,通过Client 
Commands提供的子命令选项“-mkdir”可以在HDFS中创建目录。
在HDFS集群的日常使用过程时,主要通过ClientCommands类型的HDFSShell子命
令操作HDFS。Hadoop提供了多种ClientCommands类型的HDFSShell子命令,包括dfs、
envvars、classpath等,其中,dfs主要用于操作HDFS的文件和目录,是最常用的HDFSShell 
子命令。dfs常用的子命令选项如表3-1所示。
表3-1 dfs常用的子命令选项
子命令选项功能描述
-ls 查看指定目录信息
-du 查看指定目录下每个文件和子目录的大小,子目录也可以看作单独的目录,因为它也可
以存在子目录
-mv 移动指定文件或目录
-cp 复制指定文件或目录
-rm 删除指定文件或目录
-put 将本地文件系统中的指定文件上传到HDFS指定目录
-cat 查看指定文件的内容
-help 查看帮助文档
-mkdir 创建目录
-get 将HDFS的指定文件下载到本地文件系统 
表3-1只介绍了HDFSShell子命令dfs常用的子命令选项,如果需要了解dfs其他的子

第3章 HDFS分布式文件系统 61 
命令选项,可以通过dfs提供的子命令选项“-help”进行查看。接下来对表3-1中的子命令选
项进行讲解。
1.-ls 
-ls用于查看HDFS指定目录信息,语法格式如下。 
hdfs dfs -ls [-S][-C][-r][-h][-R]<path> 
上述语法格式中,各参数的介绍具体如下。
● 参数-S:可选,用于根据文件的大小,按照由大到小的顺序显示指定目录的内容。
● 参数-C:可选,用于显示指定目录下文件和子目录的路径,不显示关于文件和子目录的
其他信息。
● 参数-r:可选,用于根据文件的大小,按照由小到大的顺序显示指定目录的内容。
● 参数-h:可选,用于将默认的文件大小(字节数)格式化为便于查看的格式进行显示,例
如将1024格式化为1MB。
● 参数-R:可选,用于递归显示指定目录及其子目录的信息。
● 参数path:用于指定查看的目录。
假设HDFS存在目录/data,该目录下包含文件dataA、dataB和子目录/dataChild,子目录
/dataChild中存在文件dataC。接下来演示如何使用子命令选项-ls查看HDFS指定目录信息。
(1)查看目录/data的信息,具体命令如下。 
$ hdfs dfs -ls -S /data 
上述命令的执行效果如图3-7所示。
图3-7 查看目录/data的信息(1) 
图3-7显示了3条信息,每条信息从左到右依次表示属性、副本数、所有者、所属组、大小
图3-8 属性每部分的含义
(子目录大小为0)、创建时间和路径。其中,属性包含4部
分内容,以drwxr-xr-x 为例,属性每部分的含义如
图3-8所示。
在图3-8中,属性每部分含义的介绍如下。
① 用于标识文件或目录,目录使用d表示,文件使用
“-”表示。
② 用于标识所有者的操作权限,包括读(r)、写(w)和执行(x)3种权限,这3部分的位置
固定,如不存在读、写或执行权限,则对应位置使用字符“-”代替。图3-8展示的所有者操作权
限是读、写和执行。
③ 用于标识用户所属组的其他用户的操作权限,图3-8展示的用户所属组的其他用户的

Hadoop大数据技术原理与应用(第62 2版) 
操作权限为读和执行。
④ 用于标识其他组用户的操作权限,图3-8展示的其他组用户的操作权限为读和执行。
(2)根据文件的大小,按照由小到大的顺序显示目录/data的内容,并将默认的文件大小
格式化为便于查看的格式进行显示,具体命令如下。 
$ hdfs dfs -ls -r -h /data 
上述命令的执行效果如图3-9所示。
图3-9 查看目录/data的信息(2) 
从图3-9可以看出,文件dataA 和dataB的大小由字节数格式化为便于查看的格式,并且
文件按照由小到大的顺序显示。
(3)递归显示目录/data及其子目录的信息,信息中仅显示文件和子目录的路径,具体命
令如下。 
$ hdfs dfs -ls -R -C /data 
上述命令的执行效果如图3-10所示。
图3-10 查看目录/data的信息(3) 
从图3-10可以看出,不仅显示了目录/data的信息,而且显示了目录/data/dataChild的
信息。
2.-mkdir 
-mkdir用于创建目录,语法格式如下。 
hdfs dfs -mkdir [-p]<path> 
上述语法格式中,参数-p为可选,它有两个作用,第一是创建目录,如果要创建的目录存
在,则不会返回错误信息,也不会重新创建;第二是递归创建目录及其子目录。
接下来,在HDFS的目录/data中创建子目录/dataChild1,并在子目录/dataChild1中创

第3章 HDFS分布式文件系统 63 
建子目录/dataChild2,具体命令如下。 
$ hdfs dfs -mkdir -p /data/dataChild1/dataChild2 
上述命令执行完成后,执行“hdfsdfs-ls-R/data”命令递归显示目录/data及其子目录的
信息,如图3-11所示。
图3-11 查看目录/data的信息(4) 
从图3-11可以看出,目录/data存在子目录dataChild1,并且该子目录同样存在子目录
/dataChild2。
3.-du 
-du用于查看HDFS指定目录下每个文件和子目录的大小,语法格式如下。 
hdfs dfs -du [-s][-h]<path> 
上述语法格式中,参数-s为可选,用于查看指定目录下所有文件和子目录的总大小;参数-h 
为可选,用于将默认的文件和子目录大小(字节数)格式化为便于查看的格式进行显示,例如将
1024格式化为1MB。
接下来演示如何使用子命令选项-du查看HDFS的目录/data中的每个文件和子目录的
大小,并将默认的文件和子目录大小格式化为便于查看的格式进行显示,具体命令如下。 
$ hdfs dfs -du -h /data 
上述命令的执行效果如图3-12所示。
图3-12 查看目录/data中每个文件和子目录的大小
从图3-12可以看出,文件和子目录的大小显示了两部分,前者为文件或子目录中文件的
实际大小,后者为文件及其副本的大小,以文件dataA 为例,文件dataA 的实际大小为
311.8MB。由于HDFS的副本数为2,所以除文件dataA 自身外,还存在一个副本,这两者大
小之和便是623.6MB。

Hadoop大数据技术原理与应用(第64 2版) 
4.-mv 
-mv用于移动HDFS指定目录或文件,语法格式如下。 
hdfs dfs -mv <src> <dst> 
上述语法格式中,参数src用于指定要移动的目录或文件。参数dst用于将目录或文件移
动到指定的目录,如果指定的目录不存在,并且与移动的目录或文件处于同一路径下,那么会
对文件或者目录进行重命名操作。需要注意的是,移动的目录或文件在指定的目录中不能
存在。接
下来演示如何使用子命令选项-mv移动HDFS的目录/data中的文件和子目录。
(1)将目录/data中的子目录/dataChild1移动到目录/data/dataChild中,具体命令如下。 
$ hdfs dfs -mv /data/dataChild1 /data/dataChild 
上述命令执行完成后,执行“hdfsdfs-ls-R/data”命令递归显示目录/data及其子目录的
信息,如图3-13所示。
图3-13 查看目录/data的信息(5) 
从图3-13可以看出,目录/data的子目录/dataChild1已经移动到目录/data/dataChild中。
(2)将目录/data中的文件dataA 重命名为dataA_New,具体命令如下。 
$ hdfs dfs -mv /data/dataA /data/dataA_New 
上述命令执行完成后,执行“hdfsdfs-ls/data”命令查看目录/data的信息,如图3-14 
所示。
图3-14 查看目录/data的信息(6) 
从图3-14可以看出,目录/data下的文件dataA 变为dataA_New。
5.-cp 
-cp用于复制HDFS指定目录或文件,语法格式如下。 
hdfs dfs -cp <src> <dst>

第3章 HDFS分布式文件系统 65 
上述语法格式中,参数src用于指定要复制的目录或文件,可以同时复制多个文件或目
录,每个文件或目录用空格进行分隔。参数dst用于将目录或文件复制到指定的目录,该目录
必须已经存在,且要复制的文件或目录在指定的目录中不能存在。如果复制的是单文件或目
录,则可以重命名复制后的文件或目录名称。
接下来演示如何使用子命令选项-cp复制HDFS的目录/data中的文件和子目录。
(1)将目录/data下的文件dataA_New 和dataB复制到目录/data/dataChild,具体命令
如下。 
$ hdfs dfs -cp /data/dataA_New /data/dataB /data/dataChild 
上述命令执行完成后,执行“hdfsdfs-ls-R/data”命令递归显示目录/data及其子目录的
信息,如图3-15所示。
图3-15 查看目录/data的信息(7) 
从图3-15可以看出,目录/data/dataChild中已经存在文件dataA_New和dataB。
(2)将目录/data 下的文件dataA_New 复制到子目录/dataChild,并将其重命名为
dataA,具体命令如下。 
$ hdfs dfs -cp /data/dataA_New /data/dataChild/dataA 
上述命令执行完成后,执行“hdfsdfs-ls/data/dataChild”命令查看目录/data/dataChild 
的信息,如图3-16所示。
图3-16 查看目录/data/dataChild的信息
从图3-16可以看出,目录/data/dataChild中存在文件dataA。
6.-rm 
-rm 用于删除HDFS指定目录或文件,语法格式如下。 
hdfs dfs -rm [-f][-r][-skipTrash][-safely]<src>

Hadoop大数据技术原理与应用(第66 2版) 
上述语法格式中,参数-f为可选,用于判断删除的目录或文件是否存在;参数-r为可选,用
于递归删除指定目录中的所有子目录和文件;参数-skipTrash为可选,表示删除的文件或目录不
会放入回收站;参数-safely为可选,用于启动安全确认,删除目录时会提示是否删除,以免误删。
接下来演示如何使用子命令选项-rm 删除目录/data的子目录/dataChild,具体命令如下。 
$ hdfs dfs -rm -r /data/dataChild 
上述命令的执行效果如图3-17所示。
图3-17 删除目录/data的子目录/dataChild 
从图3-17可以看出,目录/data的子目录/dataChild被删除并放入回收站了,同时显示了
该目录在回收站的位置。
7.-put 
-put用于将本地文件系统中的指定文件上传到HDFS指定目录,语法格式如下。 
hdfs dfs -put [-f]<localsrc> <dst> 
上述语法格式中,参数-f为可选,用于判断上传的文件在HDFS指定目录中是否存在,如
果存在,则上传的文件会替换HDFS指定目录中已经存在的文件;参数localsrc用于指定本地
文件系统中上传的文件,可以同时上传多个文件;参数dst用于指定上传到HDFS的目录,该
目录必须存在。
假设本地文件系统的/export/data目录下存在两个文件a.txt和b.txt,其中,文件a.txt 
的内容为HelloHDFS;文件b.txt的内容为HelloHadoop。接下来演示如何使用子命令选
项-put将本地文件系统中/export/data目录下的文件a.txt和b.txt上传到HDFS的目录/data, 
具体命令如下。 
$ hdfs dfs -put /export/data/a.txt /export/data/b.txt /data 
上述命令执行完成后,执行“hdfsdfs-ls/data”命令查看目录/data的信息,如图3-18 
所示。
图3-18 查看目录/data的信息(8)

第3章 HDFS分布式文件系统 67 
从图3-18可以看出,HDFS的目录/data中存在文件a.txt和b.txt,说明已成功将本地文
件上传到HDFS。
8.-cat 
-cat用于查看HDFS指定文件的内容,语法格式如下。 
hdfs dfs -cat <src> 
上述语法格式中,参数src用于指定查看的文件。接下来演示如何使用子命令选项-cat 
查看目录/data中的文件a.txt的内容,具体命令如下。 
$ hdfs dfs -cat /data/a.txt 
上述命令执行完成的效果如图3-19所示。
图3-19 查看目录/data中文件a.txt的内容
从图3-19可以看出,目录/data中文件a.txt的内容为HelloHDFS,说明已成功查看到
HDFS中的a.txt文件。
9.-get 
-get用于将HDFS的指定文件下载到本地文件系统的指定目录,语法格式如下。 
hdfs dfs -get [-f]<src> <localdst> 
上述语法格式中,参数-f为可选,用于判断下载的文件在本地文件系统的指定目录中是否
存在,如果存在,则下载的文件会替换指定目录中已存在的文件;参数src用于指定HDFS中
的文件,可以同时下载多个文件;参数localdst用于指定下载到本地文件系统的路径,该路径
必须存在。
接下来演示如何使用子命令选项-get将HDFS中目录/data中的文件a.txt和b.txt下载
到本地文件系统的/opt目录下,具体命令如下。 
$ hdfs dfs -get /data/a.txt /data/b.txt /opt 
上述命令执行完成后,在本地文件系统执行“ll/opt”命令查看目录/opt的内容,如图3-20 
所示。
图3-20 查看目录/opt的内容

Hadoop大数据技术原理与应用(第68 2版) 
从图3-20可以看出,本地文件系统的目录/opt中存在文件a.txt和b.txt,说明已成功将
HDFS上的文件下载到本地。
3.5.2 案例———通过Shell脚本定时采集数据到HDFS 
在实际的开发环境中,服务器每天都会产生大量的日志文件,这些日志文件会记录服务器
的运行状态。当服务器宕机时,可以从日志文件中查找服务器宕机的原因,从而尽快让服务器
恢复正常运行。为了方便地分析日志文件,通常采用Shell脚本周期性地将日志文件上传到
HDFS,如每隔1小时将日志文件上传到HDFS上。同样,合理的规划有助于帮助人们在个人
发展中明确方向和目标,提高自我认知和决策能力,同时提高工作效率和质量。
接下来通过一个案例演示如何通过Shell脚本周期性地将Hadoop的日志文件上传到
HDFS,本案例的Hadoop日志文件数据来自第2章中完全分布式模式部署的Hadoop集群在
运行时产生的数据。
1.创建Shell脚本
在虚拟机Hadoop1的/export/data目录下执行“viuploadHDFS.sh”命令,编辑Shell脚
本文件uploadHDFS.sh,在该文件中实现上传Hadoop日志文件到HDFS的代码,具体代码
如文件3-1所示。
文件3-1 uploadHDFS.sh 
1 #! /bin/bash 
2 export HADOOP_HOME=/export/servers/hadoop-3.3.0 
3 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin 
4 hadoop_log_dir=/export/servers/hadoop-3.3.0/logs/ 
5 log_toupload_dir=/export/data/logs/toupload/ 
6 date=`date +%Y_%m_%d_%H_%M` 
7 hdfs_dir=/hadoop_log/$date/ 
8 if [-d $log_toupload_dir ]; 
9 then 
10 echo "$log_toupload_dir exits" 
11 else 
12 mkdir -p $log_toupload_dir 
13 if 
14 ls $hadoop_log_dir | while read fileName 
15 do 
16 if [[$fileName == *.log ]]; 
17 then 
18 echo "moving hadoop log to $log_toupload_dir" 
19 cp $hadoop_log_dir/*.log $log_toupload_dir 
20 scp root@hadoop2:$hadoop_log_dir/*.log $log_toupload_dir 
21 scp root@hadoop3:$hadoop_log_dir/*.log $log_toupload_dir 
22 echo "moving hadoop log willDoing" 
23 break 
24 if 
25 done 
26 echo "create $hdfs_dir" 
27 hdfs dfs -mkdir -p $hdfs_dir 
28 ls $log_toupload_dir | while read fileName 
29 do 
30 echo "upload hadoop log $fileName to $hdfs_dir" 
31 hdfs dfs -put $log_toupload_dir$fileName $hdfs_dir 
32 echo "upload hadoop log $fileName willDoing" 
33 done 
34 echo "delete $log_toupload_dir log" 
35 rm -fr $log_toupload_dir

第3章HDFS分布式文件系统69 

上述代码中,第2~3行代码添加了Hadoop的环境变量,以免脚本执行时无法使用
HDFS的Shel 
命令。
第4行代码定义变量hadoop_log_dir,指定Hadoop的日志文件存放到目录/exort/ 
sevrs/hdo-3.3.lg/。
p

reaop0/os 
第5行代码定义变量log_toupload_dir,指定收集不同虚拟机中Hadoop日志文件的目
录/export/data/logs/toupload/。
第6行代码定义变量date,指定获取当前系统时间的年(%Y )、月(%m )、日(%d )、时(%H) 
和分(%M),并通过字符“_”拼接为字符串。
第7行代码定义变量hdfs_dir,指定Hadoop日志文件上传到HDFS的目录/hadoop_log/
$date/,其中,目录中的$date表示使用变量date代替。
第8~13行代码用于判断存放不同服务器中Hadoop日志文件的目录是否存在,如果不
存在,则创建该目录。

第14~25行代码用于将不同虚拟机中Hadoop的日志文件收集到目录/export/data/
logs/toupload/,其中,第19行代码用于收集当前虚拟机Hadoop1中的Hadoop日志文件;第
20行代码用于收集虚拟机Hadoop2中的Hadoop日志文件。第21行代码用于收集虚拟机
Hadoop3中的Hadoop日志文件。

第27行代码用于在HDFS中创建存放Hadoop日志文件的目录。
第28~33行代码用于遍历目录/export/data/logs/toupload/中的Hadoop日志文件,并
将这些日志文件逐个上传至HDFS的指定目录。
第35行代码用于删除目录/export/data/logs/toupload中的Hadoop日志文件,以免后续
再次执行Sheplasop日志文件时,

l 
脚本uodHDFS.h上传Hado上传重复的日志文件。
需要注意的是,由于脚本文件uploadHDFS.sh中涉及使用scp命令从其他虚拟机获取文件
的操作,所以为了脚本文件uploash运行过程的连续性,避免出现输入密码的操作,

dHDFS.这里
需要在配置了单向免密钥功能的虚拟机Hadop1上执行脚本文件upodHDFS.h。

olas

2.执行Shel 
脚本
进入虚拟机Hadoop1的/export/data/目录,确保Hadoop集群处于启动状态,执行“sh 
upodHDFS.h”命令运行Shel 
脚本文件upodHDFS.h,脚本文件运行完成后的效果如图3-21

laslas
所示
。



图3-21 
脚本文件运行完成后的效果


Hadoop大数据技术原理与应用(第70 2版) 
图3-21展示的脚本文件uploadHDFS.sh的输出信息中,首先将Hadoop的日志文件收集
到目录/export/data/logs/toupload,然后在HDFS中创建目录/hadoop_log/2022_10_17_17_ 
08/,并将目录/export/data/logs/toupload收集的Hadoop日志文件上传到目录/hadoop_log/ 
2022_10_17_17_08/,最后删除目录/export/data/logs/toupload中的Hadoop日志文件。
3.验证Hadoop日志文件是否上传成功
在本地计算机的浏览器中打开HDFS 的Web UI,查看HDFS 的/hadoop_log/2022_ 
10_17_17_08/目录中是否存在Hadoop日志文件,如图3-22所示。
图3-22 验证Hadoop日志文件是否上传成功
从图3-22可以看出,HDFS的/hadoop_log/2022_10_17_17_08/目录中存在Hadoop日志
文件,如日志文件hadoop-root-datanode-hadoop2.log 用于记录虚拟机Hadoop2 中的
DataNode服务在运行过程中产生的日志信息,说明已成功将Hadoop日志文件上传到HDFS 
的指定目录。
4.定时执行Shell脚本文件
下面通过Linux提供的定时任务工具Crontab定时运行Shell脚本文件uploadHDFS.sh, 
实现周期性地将Hadoop的日志文件上传到HDFS。
(1)在虚拟机Hadoop1上执行“rpm-qa|grepcrontab”命令,检查是否安装了Crontab, 
如图3-23所示。
图3-23中出现了Crontab 的版本号为1.11,因此说明虚拟机Hadoop1 已经安装了
Crontab。若没有显示Crontab 的版本信息,则说明没有安装Crontab,此时可以先安装
Crontab,具体命令如下。 
$ yum -y install vixie-cron 
$ yum -y install crontabs

第3章 HDFS分布式文件系统 71 
图3-23 检查虚拟机Hadoop1是否安装了Crontab 
(2)使用Crontab时,必须保证Crontab服务处于运行状态,启动Crontab服务的命令如下。 
$ service crond start 
上述命令执行完成后,执行“servicecrondstatus”命令验证Crontab服务是否启动成功, 
如图3-24所示。
图3-24 验证Crontab服务是否启动成功
图3-24中出现了“Active:active(running)”的提示信息,说明Crontab服务已启动成功。
若Crontab服务启动失败,则会出现“Active:inactive(dead)”的提示信息。
(3)进入虚拟机Hadoop1的/export/data/目录,为Shell脚本文件uploadHDFS.sh添加
可执行权限,这样做的目的是通过Crontab的定时任务运行Shell脚本文件uploadHDFS.sh, 
具体命令如下。 
$ chmod 777 uploadHDFS.sh 
(4)在虚拟机Hadoop1上执行“crontab-e”命令编辑Crontab文件,配置定时任务,在
Crontab文件中添加如下内容。 
*/10 * * * * /export/data/uploadHDFS.sh 
上述内容配置的定时任务表示每10分钟运行一次Shell脚本文件uploadHDFS.sh。由
于定时任务工具Crontab的使用并非本书的重点,所以上述配置定时任务的内容读者了解即