干货图文详解 HDFS 的工作机制及其原理

网友投稿 1427 2022-05-29

HDFS 是基于 流数据 访问模式的 分布式 文件系统(HDFS放宽了一部分 POSIX约束 ,来实现 流式读取 文件系统数据的目的),支持存储 海量 的数据,可以运行在 低成本 的硬件上。其提供 高吞吐量 、高容错性 的数据访问,非常适合大规模数据集上的应用。了解 HDFS 的工作机制,可以加深我们对分布式系统的理解,以及增强遇到问题时的分析解决能力,以下介绍下 HDFS 的工作机制。

如果想了解 HDFS ,可以参考这篇文章:HDFS 及其组成框架介绍 。

一、 机架感知

机架感知的设计,考虑到两个方面:

不同节点之间的通信,希望在同一机架内进行(Hadoop集群会分布在很多机架上),而不是跨机架;

为了提高 容错 能力,NameNode (名称节点)会尽可能把 数据块的副本 放在多个机架上。

DataNode 的网络拓扑图如下:

如上图,D1、R1是交换机,最底层是 DataNode 。可执行脚本文件返回各 DataNode 的机架 ID ,即 RackID(比如,H1 的 parent 是R1,R1的 parent 是D1,则 H1 的 RackID=/D1/R1/H1)。

有了这些 RackID 信息,就可以计算任意两台 DataNode 之间的距离了:

distance(/D1/R1/H1,/D1/R1/H1)=0 //相同的 DataNode distance(/D1/R1/H1,/D1/R1/H2)=2 //同一个 Rack 下不同的 DataNode distance(/D1/R1/H1,/D1/R1/H4)=4 //同一 IDC 下不同的 DataNode distance(/D1/R1/H1,/D2/R3/H7)=6 //不同 IDC 下的 DataNode

~IDC是互联网数据中心,可以理解为机房。~

默认情况下,HDFS 不能 自动判断 集群中各个 DataNode 的网络拓扑情况,集群 默认都 处在同一个机架名为 /default-rack的机架上(在这种情况下,任何一台 DataNode 机器,不管在物理上是否是属于同一个机架,都会被认为是在同一个机架下)。

通常,我们通过 外在脚本 实现机架感知,需要配置 net.topology.script.file.name属性(属性值一般是一个可执行脚本文件的路径)。脚本接收一个值,再输出一个值(一般都是接收 IP地址 ,输出这个地址所对应的 机架信息 )。

二、 副本冗余存储策略

HDFS 上的文件对应的数据块保存有多个副本(默认保存3个副本),且提供 容错机制 ,副本 丢失 或 宕机(即 死机) 时自动恢复。

下面,以保存 3个副本 为例:

第一个副本(副本一):放置在 上传文件 的数据节点上(若是在 集群外 提交,则随机挑选一个 CPU比较空闲、磁盘不太满 的节点)。

第二个副本(副本二):放置在与第一个副本 不同 的机架的节点上。

第三个副本(副本三):放置在与第二个副本 相同 机架的其他节点上。

如果有 更多 副本,那么这些副本 随机选择 节点存放。

需要注意的是,副本并不都是均匀分布在不同的机架上。

副本冗余存储策略,主要有三个优点:

减少了机架间的 数据传输 ,提高了写操作的效率。(不会影响数据的可靠性和可用性,因为机架的错误远远比节点的错误小)

减少了 读取数据 时所需的网络传输总带宽。(因为数据块只放在两个不同的机架上)

在不损害数据 可靠性 和 读取性能 的情况下,改进了写操作的性能。(一个副本在一个机架的一个节点上,另外两个副本在另一个机架的不同节点上,其他副本则 均匀分布 在剩下的机架中。如 2.1 所介绍。)

三、 文件传输过程

在 HDFS 中 读写数据 的过程都是通过数据流完成的。HDFS 提供了数据流的 I/O操作类(包括 FSDataInputStream 和 FSDataOutputStream )

HDFS 文件读取(即 数据下载)过程如图所示:

⑴ HDFS 客户端通过 DistributeFileSystem 对象的 open() 方法打开需要读取的文件。

⑵ DistributeFileSystem 向远程的 NameNode 节点发起 RPC调用 ,得到文件的数据块信息,返回数据块列表。(对于每个数据块,NameNode 返回该数据块的 DataNode 地址)

⑶ DistributeFileSystem 返回一个 FSDataInputStream 对象给客户端,客户端调用 FSDataInputStream 对象的 read() 方法读取数据。

干货,图文详解 HDFS 的工作机制及其原理

⑷ 通过对数据流反复调用 read() 方法,把数据从数据节点传输到客户端。

⑸ 当一个节点的数据读取完毕时, DFSInputStream 对象会关闭与此数据节点的连接,然后连接此文件 下一个数据块 的最近数据节点。

⑹ 当客户端读取完数据时,调用 FSDataInputStream 对象的 close() 方法关闭输入流。

FSDataInputStream 输入流类的常用方法:

pos 指定从输入流中读取数据的位置;offset 指定数据写入缓冲区的位置(偏移量);len 指定读操作的最大字节数。

HDFS 文件写入(即 数据上传)过程如图所示:

⑴ 客户端调用 DistributedFileSystem 对象的 create() 方法创建一个文件输出流对象。

⑵ DistributedFileSystem 对象远程的 NameNode 节点发起一次 RPC调用 ,NameNode 检查这个文件 是否存在 ,以及客户端 是否有权限 新建文件。

⑶ 客户端调用 FSDataOutputStream 对象的 write() 方法写数据(数据鲜卑写入缓冲区,再被切分为一个个数据包)。

⑷ 每个数据包被发送到由 NameNode 节点分配的一组数据节点中的一个数据节点上,在这组数据节点组成的管道上依次传输数据包。

⑸ 管道上的节点按反向顺序返回确认信息,最终由管道的第一个数据节点将整条管道的确认信息发送给客户端。

⑹ 客户端完成写入,调用 close() 方法关闭文件输出流。

⑺ 通知 NameNode 文件写入成功。

FSDataOutputStream 输入流类的常用方法:

len 指定读操作的最大字节数。

四、 数据容错

HDFS 能够在出错的情况下,保证 数据存储 的可靠性。常见的出错情况有 NameNode 节点出错、DataNode 节点出错 和 数据出错 这三种情况。

HDFS 中所有元数据都保存在 NameNode (名称节点)上,NameNode 节点维护 edits 和 fsimage 这两个文件。(如果这两个文件损坏,HDFS 就会 失效 )

Hadoop 提供了两个机制,来确保 NameNode 的安全:

把 NameNode 节点上的元数据信息同步存储到其他文件系统(比如 NFS ),当 NameNode 出现故障时,HDFS 自动切换到备用的 NameNode 上(HDFS HA ,就是采用共享存储系统来存储 edits 的)。

运行一个 SecondaryNameNode 节点,当 NameNode 宕机时,利用 SecondaryNameNode 的元数据信息进行系统恢复(仍然会有 部分数据 丢失)。

通常,这 两个方法 结合使用。

NameNode 通过 心跳信号 来检测近期不发送心跳信号的 DataNode,并将其标志为 宕机 (每个 DataNode 周期性地向 NameNode 发送心跳信号),不再发送 新的 I/O请求 给它们。

数据块需要重新复制的情况:

某个 DataNode 节点丢失;

DataNode 上的硬盘出错;

某个副本损坏;

某个数据块的副本系数低于设定值。

从 DataNode 获取的数据块,有可能本身就是损坏的(比如可能是因为 网络错误 、软件bug 或者 DataNode的存储设备错误)。

HDFS 使用 校验和来判断数据块是否损坏。HDFS 的每个 DataNode 节点,保存了检测校验的日志(客户端的每一次检验都会被记录)。

BigData Pro 大数据 大数据

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:智慧教育云:解决传统教育难题
下一篇:性能分析之性能建模简述
相关文章