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

举报
烟雨江南 发表于 2021/04/28 12:32:24 2021/04/28
【摘要】 介绍了 机架感知(通过HDFS网络拓扑图介绍)、副本冗余存储策略及其优点, HDFS文件读取、写入的详细过程(HDFS数据上传 、 下载 过程的分析),FSDataInputStream 类、FSDataOutputStream 类的常用方法,以及 数据容错 的有关知识。

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

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


一、 机架感知

1.1 设计机架感知的目的

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

  1. 不同节点之间的通信,希望在同一机架内进行(Hadoop集群会分布在很多机架上),而不是跨机架;
  2. 为了提高 容错 能力,NameNode (名称节点)会尽可能把 数据块的副本 放在多个机架上。

1.2 通过网络拓扑图分析

1.2.1 网络拓扑图介绍

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是互联网数据中心,可以理解为机房。~

1.2.2 功能分析

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

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

二、 副本冗余存储策略

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

2.1 策略的介绍

下面,以保存 3个副本 为例:
在这里插入图片描述

  1. 第一个副本(副本一):放置在 上传文件 的数据节点上(若是在 集群外 提交,则随机挑选一个 CPU比较空闲磁盘不太满 的节点)。
  2. 第二个副本(副本二):放置在与第一个副本 不同 的机架的节点上。
  3. 第三个副本(副本三):放置在与第二个副本 相同 机架的其他节点上。
  4. 如果有 更多 副本,那么这些副本 随机选择 节点存放。

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

2.2 策略的优点

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

  1. 减少了机架间的 数据传输 ,提高了写操作的效率。(不会影响数据的可靠性和可用性,因为机架的错误远远比节点的错误小)
  2. 减少了 读取数据 时所需的网络传输总带宽。(因为数据块只放在两个不同的机架上)
  3. 在不损害数据 可靠性 和 读取性能 的情况下,改进了写操作的性能。(一个副本在一个机架的一个节点上,另外两个副本在另一个机架的不同节点上,其他副本则 均匀分布 在剩下的机架中。如 2.1 所介绍。)

三、 文件传输过程

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

3.1 文件读取

3.1.1 读取过程分析

HDFS 文件读取(即 数据下载)过程如图所示:
在这里插入图片描述

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

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

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

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

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

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

3.1.2 FSDataInputStream 类介绍

FSDataInputStream 输入流类的常用方法:

方法名 返回值 作用
read(ByteBuffer buf) int 读取并写入 buf 缓冲区,返回所读的字节数
read(long pos,byte[] buf,int offset,int len) int 从输入流的指定位置开始,把数据读入缓冲区。
readFully(long pos,byte[] buf) void 从指定位置开始,读取所有数据到缓冲区
seek(long offset) void 指向输入流的第 offset 字节
releaseBuffer(ByteBuffer buf) void 删除指定的缓冲区

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

3.2 文件写入

3.2.1 写入过程分析

HDFS 文件写入(即 数据上传)过程如图所示:
在这里插入图片描述

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

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

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

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

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

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

⑺ 通知 NameNode 文件写入成功。

3.2.2 FSDataOutputStream 类介绍

FSDataOutputStream 输入流类的常用方法:

方法名 返回值 作用
write(byte[] b) void 将数组 b 中的所有字节写入输出流
write(byte[] buf,int off,int len) void 将字节组写入底层输出流,写入的字节从 off 偏移量开始,写入长度为 len
flush() void 刷新数据输出流(缓冲区内容被强制写入流中)

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

四、 数据容错

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

4.1 分析 NameNode 节点出错

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

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

  1. 把 NameNode 节点上的元数据信息同步存储到其他文件系统(比如 NFS ),当 NameNode 出现故障时,HDFS 自动切换到备用的 NameNode 上(HDFS HA ,就是采用共享存储系统来存储 edits 的)。
  2. 运行一个 SecondaryNameNode 节点,当 NameNode 宕机时,利用 SecondaryNameNode 的元数据信息进行系统恢复(仍然会有 部分数据 丢失)。
    通常,这 两个方法 结合使用。

4.2 分析 DataNode 节点出错

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

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

  1. 某个 DataNode 节点丢失;
  2. DataNode 上的硬盘出错;
  3. 某个副本损坏;
  4. 某个数据块的副本系数低于设定值。

4.3 分析 数据出错

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

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


文章来源: https://blog.csdn.net/qq_45069279 ,作者:苜苜的烂笔头,版权归原作者所有,如需转载,请联系作者。

原文链接:https://blog.csdn.net/qq_45069279/article/details/114734679

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。