干货,图文详解 HDFS 的工作机制及其原理
HDFS 是基于 流数据 访问模式的 分布式 文件系统(HDFS放宽了一部分 POSIX约束 ,来实现 流式读取 文件系统数据的目的),支持存储 海量 的数据,可以运行在 低成本 的硬件上。其提供 高吞吐量 、高容错性 的数据访问,非常适合大规模数据集上的应用。了解 HDFS 的工作机制,可以加深我们对分布式系统的理解,以及增强遇到问题时的分析解决能力,以下介绍下 HDFS 的工作机制。
如果想了解 HDFS ,可以参考这篇文章:HDFS 及其组成框架介绍 。
一、 机架感知
1.1 设计机架感知的目的
机架感知的设计,考虑到两个方面:
- 不同节点之间的通信,希望在同一机架内进行(Hadoop集群会分布在很多机架上),而不是跨机架;
- 为了提高 容错 能力,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个副本 为例:
- 第一个副本(副本一):放置在 上传文件 的数据节点上(若是在 集群外 提交,则随机挑选一个 CPU比较空闲、磁盘不太满 的节点)。
- 第二个副本(副本二):放置在与第一个副本 不同 的机架的节点上。
- 第三个副本(副本三):放置在与第二个副本 相同 机架的其他节点上。
- 如果有 更多 副本,那么这些副本 随机选择 节点存放。
需要注意的是,副本并不都是均匀分布在不同的机架上
。
2.2 策略的优点
副本冗余存储策略,主要有三个优点:
- 减少了机架间的 数据传输 ,提高了写操作的效率。(不会影响数据的可靠性和可用性,因为机架的错误远远比节点的错误小)
- 减少了 读取数据 时所需的网络传输总带宽。(因为数据块只放在两个不同的机架上)
- 在不损害数据 可靠性 和 读取性能 的情况下,改进了写操作的性能。(一个副本在一个机架的一个节点上,另外两个副本在另一个机架的不同节点上,其他副本则 均匀分布 在剩下的机架中。如 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 的安全:
- 把 NameNode 节点上的元数据信息同步存储到其他文件系统(比如 NFS ),当 NameNode 出现故障时,HDFS 自动切换到备用的 NameNode 上(HDFS HA ,就是采用共享存储系统来存储 edits 的)。
- 运行一个 SecondaryNameNode 节点,当 NameNode 宕机时,利用 SecondaryNameNode 的元数据信息进行系统恢复(仍然会有 部分数据 丢失)。
通常,这 两个方法 结合使用。
4.2 分析 DataNode 节点出错
NameNode 通过 心跳信号 来检测近期不发送心跳信号的 DataNode,并将其标志为 宕机 (每个 DataNode 周期性地向 NameNode 发送心跳信号),不再发送 新的 I/O请求 给它们。
数据块需要重新复制的情况:
- 某个 DataNode 节点丢失;
- DataNode 上的硬盘出错;
- 某个副本损坏;
- 某个数据块的副本系数低于设定值。
4.3 分析 数据出错
从 DataNode 获取的数据块,有可能本身就是损坏的(比如可能是因为 网络错误 、软件bug 或者 DataNode的存储设备错误)。
HDFS 使用 校验和
来判断数据块是否损坏。HDFS 的每个 DataNode 节点,保存了检测校验的日志(客户端的每一次检验都会被记录)。
文章来源: https://blog.csdn.net/qq_45069279 ,作者:苜苜的烂笔头,版权归原作者所有,如需转载,请联系作者。
原文链接:https://blog.csdn.net/qq_45069279/article/details/114734679
- 点赞
- 收藏
- 关注作者
评论(0)