目录
(3) SecondaryNameNode:辅助NameNode进行元数据合并
前言
Hadoop分布式文件系统(HDFS)是大数据领域的关键组件,负责大规模数据的可靠存储与管理。通过探索HDFS的基础知识、工作机制及其内在原理,将增进对这一技术的理解,并为实际应用提供有力支持。
一、HDFS分布式文件系统基础
1.数据与元数据
在HDFS分布式文件系统中,首先需要明确两个核心概念:数据和元数据。
- 数据:这是指实际存储的内容,如文本文件、视频、图片等。这些数据是用户实际关心和操作的对象。
- 元数据:又称为解释性数据,它是描述其他数据的数据。在文件系统的上下文中,元数据通常包括文件大小、最后修改时间、底层存储位置、属性和所属用户的权限等信息。这些元数据对于文件系统的正常运行至关重要,因为它们提供了文件和文件系统的结构和属性的详细描述。
2.分布式存储系统的核心属性
HDFS作为一个分布式存储系统,具有以下核心属性:
- 分布式存储:数据和元数据在多个节点上进行存储,提高了数据的可靠性和可访问性。
- 元数据记录:每个文件和其相关的元数据都在系统中进行记录,以便于管理和检索。
- 分块存储:大文件被分割成多个较小的数据块进行存储,这有助于优化存储空间和提高数据访问效率。
- 副本机制:为了增加数据的可靠性和容错性,HDFS会对每个数据块创建多个副本并存储在集群的不同节点上。
3.HDFS的设计目标
HDFS在设计时考虑了以下目标:
- 大部分HDFS应用遵循“write-one-read-many”访问模型,意味着一个文件在创建、写入和关闭后通常不需要进行修改。这有助于简化系统设计并提高读取效率。
- 移动计算的代价比移动数据的代价低,因此HDFS被设计为在计算节点附近存储数据,以减少网络拥堵和数据传输延迟。
- HDFS设计为可轻松从一个平台移植到另一个平台,这有助于在不同的硬件和软件环境中部署和使用HDFS。
4.HDFS的重要特性
HDFS通过主从架构、分块存储、副本机制、元数据管理和命名空间等特性,确保了分布式文件系统的可扩展性、可靠性、容错性和高效性。这些特性使得HDFS成为处理大规模数据集的理想选择。
- 主从架构:HDFS集群采用标准的master/slave主从架构。通常,一个HDFS集群包括一个Namenode(主节点)和多个Datanode(从节点)。Namenode负责管理文件系统的元数据和客户端的访问请求,而Datanode负责实际的数据存储和检索。这种架构确保了系统的可扩展性和可靠性。
- 分块存储:在HDFS中,文件在物理上是以数据块(block)的形式进行存储的。默认的数据块大小为128MB,但如果文件小于128MB,则该文件本身作为一个数据块。数据块的大小可以通过配置参数进行调整,以满足不同的存储需求。
- 副本机制:为了提高数据的可靠性和容错性,HDFS采用了副本机制。这意味着每个数据块都会在集群中的不同节点上创建多个副本。副本系数可以在文件创建时指定,也可以通过后续命令进行修改。默认的副本数为3,包括原始数据块和另外两个副本。
- 元数据管理:在HDFS中,Namenode负责管理两种类型的元数据:文件自身的属性信息(如文件名、权限、修改时间等)和数据块与Datanode之间的映射信息。这种映射信息记录了哪个数据块存储在哪个节点上,从而确保客户端可以通过合适的节点访问所需的数据块。
- 命名空间(Namespace):HDFS支持传统的层次型文件组织结构,允许用户创建目录并将文件保存在这些目录中。Namenode负责维护文件系统的命名空间,记录所有对文件和目录的创建、删除、移动和重命名操作。客户端通过路径来访问文件,这些路径由Namenode提供的统一抽象目录树来管理。
二、HDFS Shell操作
1.HDFS Shell命令行简介
命令行界面(Command-Line Interface,简称CLI)是用户与计算机进行交互的一种方式,用户通过键盘输入指令,计算机接收并执行这些指令。Hadoop提供了一个文件系统的shell命令客户端,用于与HDFS进行交互。
其基本语法为:
hadoop fs [generic options]
文件系统协议:
HDFS Shell CLI支持操作多种文件系统,如本地文件系统(file:///
)和分布式文件系统(hdfs://nn:8020
)等。执行何种文件系统的操作取决于命令中文件路径URL的前缀协议。如果没有指定前缀协议,则会读取环境变量中的fs.defaultFS
属性,并使用该属性值作为默认文件系统。
2.HDFS Shell常用操作
(1) 创建文件夹
语法如下:
hadoop fs -mkdir [-p] <path> …
path :要创建的目录。 | |
-p :如果路径中的父目录不存在,则一并创建。 |
示例:
hadoop fs -mkdir /user/example/dir1
(2) 查看目录内容
语法如下:
hadoop fs -ls [-h] [-R] [<path> …]
path :要查看的目录。 | |
-h :以易读的方式显示文件大小。 | |
-R :递归列出目录及其子目录的内容。 |
示例:
hadoop fs -ls -h /user/example
(3) 上传文件
语法如下:
hadoop fs -put [-f] [-p] <localsrc> … <dst>
-f :如果目标文件已存在,则覆盖它。 | |
-p :保留文件的访问时间、修改时间、所有权和权限。 | |
localsrc :本地文件系统上的源文件。 | |
dst :目标文件系统上的目标路径。 |
示例:
hadoop fs -put localfile.txt /user/example/
(4) 查看文件内容
语法如下:
hadoop fs -cat <src> …
使用此命令可以查看HDFS中文件的内容。由于内容将被直接输出到控制台,对于大文件,可能会导致显示不全或卡顿。
示例:
hadoop fs -cat /user/example/file.txt
(5) 下载文件
语法如下:
hadoop fs -get [-f] [-p] <src> … <localdst>
此命令用于将HDFS中的文件下载到本地文件系统。其中,localdst
必须是一个目录。
示例:
hadoop fs -get /user/example/file.txt /local/directory/
(6) 复制文件
语法如下:
hadoop fs -cp [-f] <src> … <dst>
在HDFS中复制文件或目录。如果目标文件已存在,可以使用-f
选项覆盖它。
示例:
hadoop fs -cp /user/example/file.txt /user/example/copyfile.txt
(7) 追加数据到文件
语法如下:
hadoop fs -appendToFile <localsrc> … <dst>
此命令允许将本地文件的内容追加到HDFS中的现有文件。如果目标文件不存在,将会创建它。
示例:
hadoop fs -appendToFile localdata.txt /user/example/file.txt
(8) 移动或重命名文件
语法如下:
hadoop fs -mv <src> … <dst>
可以使用此命令在HDFS中移动文件或将文件重命名为新名称。
示例:
hadoop fs -mv /user/example/oldname.txt /user/example/newname.txt
三、HDFS工作流程与机制
1.HDFS集群角色与职责
在HDFS集群中,主要有三个角色:NameNode、DataNode和SecondaryNameNode。它们各自承担着不同的职责。
(1) NameNode:集群的核心与元数据管理者
- NameNode是HDFS的核心组件,负责管理文件系统的元数据,包括目录树结构、文件和块的位置信息以及访问权限等。它是访问HDFS的唯一入口。
- NameNode通过内存和磁盘文件两种方式管理元数据,其中磁盘上的元数据文件包括FsImage(内存元数据镜像文件)和Edits Log(编辑日志)。
- NameNode不存储实际数据,而是存储文件的目录树和跟踪整个集群中的文件。它知道HDFS中任何给定文件的块列表及其位置,并使用此信息来构建文件。
- NameNode是Hadoop集群中的单点故障,因此通常会配置有大量内存(RAM)以支持其操作。
(2) DataNode:数据的实际存储者
- DataNode负责实际数据块的存储,是HDFS集群中的从角色,也称为Slave。它们根据NameNode的指示存储和检索数据块。
- 当DataNode启动时,它会向NameNode注册并报告其持有的块列表。如果某个DataNode关闭,不会影响数据的可用性,因为NameNode会安排其他DataNode管理的块进行副本复制。
- DataNode所在机器通常配置有大量的硬盘空间,因为实际数据存储在这些节点中。
(3) SecondaryNameNode:辅助NameNode进行元数据合并
- SecondaryNameNode充当NameNode的辅助节点,但不能替代NameNode。它的主要职责是帮助NameNode进行元数据文件的合并操作,以减轻NameNode的负担并减少其启动恢复时间。
- SecondaryNameNode定期从NameNode获取FsImage和Edits Log的合并版本,并将其存储在本地磁盘上。在紧急情况下,这可以用于恢复NameNode的状态。
2.HDFS写数据流程(上传文件)
(1) 写数据完整流程图
(2) Pipeline管道
Pipeline管道是Hadoop Distributed File System (HDFS)在上传文件和数据写入时所采用的一种数据传输策略。它的工作原理有些类似于传统的流水线生产模式:一旦数据开始流动,它就会持续不断地向前传输,直至达到目的地。
当客户端决定写入一个数据块时,它首先将数据发送到HDFS集群中的第一个数据节点。这个节点在成功存储数据块之后,会负责将数据复制到集群中的第二个数据节点。同样地,第二个数据节点在存储数据后,会将其复制到第三个数据节点。这个过程会一直持续下去,直到数据块被复制到所需的所有节点为止。
这种管道式的传输方式确保了数据能够高效、有序地从一个节点流向另一个节点,从而充分利用了每个机器的带宽。这样的设计也有助于避免网络瓶颈和高延迟连接的问题,从而最大限度地减少了推送所有数据所需的总延时。
此外,这种管道传输模式采用的是线性推送策略,这意味着每台机器都会用其所有的出口带宽来以最快的速度传输数据,而不是在多个接收者之间分配带宽。
(3) ACK应答响应
ACK (Acknowledge character)是在数据通信中常用的一个术语,它表示接收方已经成功接收到发送方发送的数据,并且数据是完整无误的。在HDFS中,ACK的作用尤为关键,因为它确保了数据的完整性和准确性。
当数据通过Pipeline管道在HDFS集群中的各个节点之间传输时,接收数据的节点会向发送数据的节点发送一个ACK信号。这个ACK信号实际上是一个校验机制,它告诉发送方:“我已经成功接收到你发送的数据,并且数据是完整的。”如果发送方没有收到ACK信号或者收到的ACK信号表示数据有误,它会重新发送数据,直到数据被成功接收为止。
(4) 默认3副本存储策略
HDFS采用了默认的三副本存储策略来确保数据的可靠性和持久性。这种策略是由BlockPlacementPolicyDefault来指定的。
- 第一块副本:HDFS会优先考虑将数据的第一个副本存储在客户端所在的本地机器上。如果客户端所在机器没有足够的存储空间或者出于其他原因不能存储数据,HDFS则会随机选择集群中的其他机器来存储数据。
- 第二块副本:为了确保数据的可靠性,第二个副本会被存储在与第一个副本不同的机架上。这样做的好处是,即使某个机架发生故障,数据仍然可以从其他机架上的副本中恢复。
- 第三块副本:第三个副本会被存储在与第二个副本相同的机架上,但是会在不同的机器上。这样做的目的是为了进一步提高数据的可靠性和容错能力。
(5) 完整流程
-
HDFS客户端创建对象实例DistributedFileSystem, 该对象中封装了与HDFS文件系统操作的相关方法。
-
调用DistributedFileSystem对象的create()方法,通过RPC请求NameNode创建文件。 NameNode执行各种检查判断:目标文件是否存在、父目录是否存在、客户端是否具有创建该文件的权限。检查通过,NameNode就会为本次请求记下一条记录,返回FSDataOutputStream输出流对象给客户端用于写数据。
-
客户端通过FSDataOutputStream输出流开始写入数据。
-
客户端写入数据时,将数据分成一个个数据包(packet 默认64k), 内部组件DataStreamer请求NameNode挑选出适合存储数据副本的一组DataNode地址,默认是3副本存储。DataStreamer将数据包流式传输到pipeline的第一个DataNode,该DataNode存储数据包并将它发送到pipeline的第二个DataNode。同样,第二个DataNode存储数据包并且发送给第三个(也是最后一个)DataNode。
-
传输的反方向上,会通过ACK机制校验数据包传输是否成功。
-
客户端完成数据写入后,在FSDataOutputStream输出流上调用close()方法关闭。
-
DistributedFileSystem联系NameNode告知其文件写入完成,等待NameNode确认。 因为namenode已经知道文件由哪些块组成(DataStream请求分配数据块),因此仅需等待最小复制块即可成功返回。最小复制是由参数dfs.namenode.replication.min指定,默认是1。
3.HDFS读数据流程(下载文件)
(1) 读数据完整流程图
(2) 完整流程
-
HDFS客户端创建对象实例DistributedFileSystem, 调用该对象的open()方法来打开希望读取的文件。
-
DistributedFileSystem使用RPC调用namenode来确定文件中前几个块的块位置(分批次读取)信息。 对于每个块,namenode返回具有该块所有副本的datanode位置地址列表,并且该地址列表是排序好的,与客户端的网络拓扑距离近的排序靠前。
-
DistributedFileSystem将FSDataInputStream输入流返回到客户端以供其读取数据。
-
客户端在FSDataInputStream输入流上调用read()方法。然后,已存储DataNode地址的InputStream连接到文件中第一个块的最近的DataNode。数据从DataNode流回客户端,结果客户端可以在流上重复调用read()。
-
当该块结束时,FSDataInputStream将关闭与DataNode的连接,然后寻找下一个block块的最佳datanode位置。这些操作对用户来说是透明的。所以用户感觉起来它一直在读取一个连续的流。
-
一旦客户端完成读取,就对FSDataInputStream调用close()方法。
总结
本文介绍了HDFS的基础知识、工作流程以及其内在机制,希望对大家有所帮助。