终于有人把HDFS架构和读写流程讲明白了

HelloKitty 2022-09-14 18:00

扫一扫 在手机阅读、分享本文

2805

作者:蒋杰 刘煜宏 陈鹏 郑礼雄 陶阳宇 罗韩梅

来源:大数据DT(ID:hzdashuju)

01 HDFS基础

以下是HDFS设计时的目标。

1. 硬件故障

硬件故障对于 HDFS 来说应该是常态而非例外。HDFS 包含数百或数千台服务器(计算机),每台都存储文件系统的一部分数据。事实上,HDFS 存在大量组件并且每个组件具有非平凡的故障概率,这意味着某些组件始终不起作用。因此,检测故障并从中快速自动恢复是 HDFS 的设计目标。

2. 流式数据访问

在 HDFS 上运行的应用程序不是通常在通用文件系统上运行的通用应用程序,需要对其数据集进行流式访问。HDFS 用于批处理而不用于用户的交互式使用,相对于数据访问的低延迟更注重数据访问的高吞吐量。

可移植操作系统接口(Portable Operating System Interface of UNIX, POSIX)标准设置的一些硬性约束对 HDFS 来说是不需要的,因此 HDFS 会调整一些 POSIX 特性来提高数据吞吐率,事实证明是有效的。

3. 超大数据集

在 HDFS 上运行的应用程序具有大型数据集。HDFS 上的一个文件大小一般在吉字节(GB)到太字节(TB)。因此,HDFS 需要设计成支持大文件存储,以提供整体较高的数据传输带宽,能在一个集群里扩展到数百上千个节点。一个 HDFS 实例需要支撑千万计的文件。

4. 简单的一致性模型

HDFS 应用需要“一次写入多次读取”访问模型。假设一个文件经过创建、写入和关闭之后就不会再改变了。这一假设简化了数据一致性问题,并可实现高吞吐量的数据访问。MapReduce 应用或网络爬虫应用都非常适合这个模型。将来还需要扩充这个模型,以便支持文件的附加写操作。

5. 移动计算而不是移动数据

当应用程序在其操作的数据附近执行时,计算效率更高。当数据集很大时更是如此,这可以最大限度地减少网络拥塞并提高系统的整体吞吐量。HDFS 为应用程序提供了接口,使其自身更靠近数据所在的位置。

6. 跨异构硬件和软件平台的可移植性

HDFS 的设计考虑到了异构硬件和软件平台间的可移植性,方便了 HDFS 作为大规模数据应用平台的推广。

从 Hadoop 这些年的发展来看,HDFS 依靠上述特性,成为不断演进变革的大数据体系的坚实基石。

02 HDFS架构

HDFS是一个典型的主/备(Master/Slave)架构的分布式系统,由一个名字节点 Namenode(Master) +多个数据节点 Datanode(Slave)组成。其中Namenode提供元数据服务,Datanode 提供数据流服务,用户通过 HDFS 客户端与 Namenode 和 Datanode 交互访问文件系统。

如图 3-1 所示 HDFS 把文件的数据划分为若干个块(Block),每个 Block 存放在一组 Datanode 上,Namenode 负责维护文件到 Block 的命名空间映射以及每个 Block 到 Datanode 的数据块映射。

1.png

▲图3-1 HDFS架构

HDFS 客户端对文件系统进行操作时,如创建、打开、重命名等,Namenode 响应请求并对命名空间进行变更,再返回相关数据块映射的 Datanode,客户端按照流协议完成数据的读写。

HDFS基本概念

HDFS 架构比较简单,但涉及概念较多,其中几个重要的概念如下:

1. 块(Block)

Block 是 HDFS 文件系统处理的最小单位,一个文件可以按照 Block 大小划分为多个 Block,不同于Linux文件系统中的数据块,HDFS 文件通常是超大文件,因此 Block 大小一般设置得比较大,默认为 128MB。

2. 复制(Replica)

HDFS 通过冗余存储来保证数据的完整性,即一个 Block 会存放在 N 个 Datanode 中,HDFS 客户端向 Namenode 申请新 Block 时,Namenode 会根据 Block 分配策略为该 Block 分配相应的 Datanode replica,这些 Datanode 组成一个流水线(pipeline),数据依次串行写入,直至 Block 写入完成。

3. 名字节点(Namenode)

Namenode 是 HDFS 文件系统的管理节点,主要负责维护文件系统的命名空间(Namespace)或文件目录树(Tree)和文件数据块映射(BlockMap),以及对外提供文件服务。

HDFS 文件系统遵循 POXIS 协议标准,与 Linux 文件系统类似,采用基于 Tree 的数据结构,以 INode 作为节点,实现一个目录下多个子目录和文件。INode 是一个抽象类,表示 File/Directory 的层次关系,对于一个文件来说,INodeFile除了包含基本的文件属性信息,也包含对应的 Block 信息。

数据块映射信息则由 BlockMap 负责管理,在 Datanode 的心跳上报中,将向 Namenode 汇报负责存储的 Block 列表情况,BlockMap 负责维护 BlockID 到 Datanode 的映射,以方便文件检索时快速找到 Block 对应的 HDFS 位置。

HDFS 每一步操作都以 FSEditLog 的信息记录下来,一旦 Namenode 发生宕机重启,可以从每一个 FSEditLog 还原出 HDFS 操作以恢复整个文件目录树,如果 HDFS 集群发生过很多变更操作,整个过程将相当漫长。

因此 HDFS 会定期将 Namenode 的元数据以 FSImage 的形式写入文件中,这一操作相当于为 HDFS 元数据打了一个快照,在恢复时,仅恢复 FSImage 之后的 FSEditLog 即可。

由于 Namenode 在内存中需要存放大量的信息,且恢复过程中集群不可用,HDFS 提供 HA(主/备 Namenode 实现故障迁移 Failover)以及 Federation(多组 Namenode 提供元数据服务,以挂载表的形式对外提供统一的命名空间)特性以提高稳定性和减少元数据压力。

4. Datanode

Datanode 是 HDFS 文件系统的数据节点,提供基于 Block 的本地文件读写服务。定期向 Namenode 发送心跳。Block 在本地文件系统中由数据文件及元数据文件组成,前者为数据本身,后者则记录 Block 长度和校验和(checksum)等信息。扫描或读取数据文件时,HDFS 即使运行在廉价的硬件上,也能通过多副本的能力保证数据一致性。

5. FileSystem

HDFS 客户端实现了标准的 Hadoop FileSystem 接口,向上层应用程序提供了各种各样的文件操作接口,在内部使用了 DFSClient 等对象并封装了较为复杂的交互逻辑,这些逻辑对客户端都是透明的。

03 HDFS读写流程

1. HDFS客户端写流程

图 3-2 所示为客户端完成 HDFS 文件写入的主流程。

2.png

▲图3-2 客户端完成HDFS写入的主流程


1)创建文件并获得租约

HDFS 客户端通过调用 DistributedFileSystem# create 来实现远程调用 Namenode 提供的创建文件操作,Namenode 在指定的路径下创建一个空的文件并为该客户端创建一个租约(在续约期内,将只能由这一个客户端写数据至该文件),随后将这个操作记录至 EditLog(编辑日志)。 Namenode 返回相应的信息后,客户端将使用这些信息,创建一个标准的 Hadoop FSDataOutputStream 输出流对象。

2)写入数据

HDFS 客户端开始向 HdfsData-OutputStream 写入数据,由于当前没有可写的 Block,DFSOutputStream 根据副本数向 Namenode 申请若干 Datanode 组成一条流水线来完成数据的写入,如图 3-3 所示。

3.png

▲图3-3 流水线数据写入示意图


3)串行写入数据,直到写完Block

客户端的数据以字节(byte)流的形式写入 chunk(以chunk为单位计算 checksum(校验和))。若干个chunk组成packet,数据以 packet 的形式从客户端发送到第一个 Datanode,再由第一个 Datanode 发送数据到第二个 Datanode 并完成本地写入,以此类推,直到最后一个 Datanode 写入本地成功,可以从缓存中移除数据包(packet),如图 3-4 所示。

4.png

▲图3-4 串行写入数据示意图


4)重复步骤2和步骤3,然后写数据包和回复数据包,直到数据全部写完。

5)关闭文件并释放租约

客户端执行关闭文件后,HDFS 客户端将会在缓存中的数据被发送完成后远程调用 Namenode 执行文件来关闭操作。

Datanode 在定期的心跳上报中,以增量的信息汇报最新完成写入的 Block,Namenode 则会更新相应的数据块映射以及在新增 Block 或关闭文件时根据Block映射副本信息判断数据是否可视为完全持久化(满足最小备份因子)。

2. HDFS客户端读流程

相对于 HDFS 文件写入流程,HDFS 读流程相对简单,如图 3-5 所示。

5.png

▲图3-5 HDFS读流程

1)HDFS 客户端远程调用 Namenode,查询元数据信息,获得这个文件的数据块位置列表,返回封装 DFSIntputStream 的 HdfsDataInputStream 输入流对象。

2)客户端选择一台可用 Datanode 服务器,请求建立输入流。

3)Datanode 向输入流中写原始数据和以 packet 为单位的 checksum。

4)客户端接收数据。如遇到异常,跳转至步骤2,直到数据全部读出,而后客户端关闭输入流。当客户端读取时,可能遇到 Datanode 或 Block 异常,导致当前读取失败。正由于 HDF S的多副本保证,DFSIntputStream 将会切换至下一个 Datanode 进行读取。与 HDFS 写入类似,通过 checksum 来保证读取数据的完整性和准确性。


文章信息来自于以下文章来源于大数据DT ,作者蒋杰 刘煜宏 等,不代表白鲸技术栈官方立场,内容仅供网友参考学习。对于因本网站内容所引起的纠纷、损失等,白鲸技术栈均不承担侵权行为的连带责任。

扫一扫 在手机阅读、分享本文

扫码关注公众号

获取更多技术资讯

精选活动 更多 >

{{ val.activity_name }}

{{ val.province ? (val.province + ' ' + val.city) : val.location }}
客服微信
享受1V1专属服务
免费领取技术福利
发送名片申请入群
与CTO聊合作
(备注姓名、公司及职位)
热门文章