HDFS 优化与容错机制

上一篇主要讲了 HDFS 的一些基础内容,包括角色职责,工作流程,可用性保证等等,这里我们要更进一步,再挖掘出一些比较有价值的内容,所以这篇主要讲解 HDFS 的容错机制和在保证系统性能的方面做的相关努力,包括机架感知,短路读,压缩,避免小文件等。另外上一篇说到了系统可用性的问题,这里的容错机制算是可用性的一个补充, 主要讲解在读写异常过程中 HDFS 是如何保证系统可用性的。

本篇面试内容划重点:Failover、机架感知、短路读、小文件问题

读写异常场景下 HDFS 的容错机制

HDFS 就像是一台精良的机器,为了保证用户体验,它不允许在用户操作的过程中出现任何的差错,所以,它在设计实现的时候就对各种异常场景做了周全的考虑,如何发现问题,如何满足用户需求的同时保证系统一致性,如何解决问题等等,下面我们来细看。 image.png

写失败场景的处理流程?

如上图,我们沿用上一篇中的读写流程图,当步骤 4的执行过程中,一台 DataNode 宕机了,想象一下,接下来会发生什么事情,当然,发生的所有事情都是对客户端透明的,DFSClient 仍然是“岁月静好”的状态。

  1. 首先 pipeline 被关闭,在确认队列中的剩下的 package 会被添加进数据队列的起始位置上不再发送,以防止在失败的节点下游的节点再丢失数据
  2. 然后,存储在正常的 datanode 上的 block 会被指定一个新的标识,并将该标识传递给 namenode,以便故障 datanode 在恢复后可以删除自己存储的那部分已经失效的数据块。
  3. 失败节点会从 pipeline 中移除,然后剩下两个好的 DataNode 会组成一个的新的 pipeline ,剩下的这些 block 的包会继续写进 pipeline 中正常的 DataNode 中。
  4. 最后,即在写流程的步骤 7 中,NameNode 会发现节点宕机导致部分 block 的块备份数小于规定的备份数,此时NameNode 会安排使节点的备份数满足 dfs.replication 配置要求
读失败场景的处理流程?

读失败的场景比较简单,再看上图右半部分,即步骤 4异常的情况。

  1. DFSInputStream 会去尝试连接列表里的下一个 DataNode ,同时记录下这个异常节点。

  2. 同时 DFSInputStream 也会对获取到的数据核查 checknums 。如果损坏的 block 被发现了,DFSInputStream 就试图从另一个拥有备份的 DataNode 中去读取备份块中的数据。

  3. 最后异常数据的同步工作也是由 NameNode 来安排完成。

  4. 客户端写 DataNode 的过程中 DataNode 宕机是否对写有影响? 单台宕机对写没有影响,客户端会找到新的健康的节点继续完成写入操作,具体见上述步骤。

  5. 是否要完成所有目标 DataNode 节点的写入,才算一次写成功操作? 写成功数量达到最小备份数的阈值即算写入成功。

  6. 读的过程如何保证数据没有被损坏,如果损坏如何处理? DFSInputStream 会在 Datanode 上传输的数据上检查 checknums 。如果有损坏,DFSInputStream 会从另一个拥有备份的 Datanode 中读取备份数据。

  7. 交互过程数据校验的基本单位 chunk 是最小的单位,也是数据校验的基本单位,默认 512Byte,每个 chunk 带有 4 Byte 的校验位。

HDFS 机架感知(rack awareness)

互联网公司的 Hadoop 集群一般都会比较大,几百台服务器会分布在不同的机架上,甚至在不同的机房。出于保证数据安全性和数据传输的高效性的平衡考虑,HDFS希望不同节点之间的通信能够尽量发生在同一个机架之内,而不是跨机架和跨机房。同时,NameNode 在分配 Block 的存储位置的时候,会尽可能把数据块的副本放到多个机架甚至机房中,防止机架出现事故或者机房出现事故时候的数据丢失问题发生。

image.png

这就是 HDFS 的机架感知,首先机房和机架的信息是需要用户自己配置的,HDFS 没法做到自动感知,然后根据配置的信息,NameNode 会有如下的副本放置策略。

  • 第一个 block 副本放在 Client 所在的服务器,如果 client 不在集群服务器中,则这第一个 DataNode 会随机选择。
  • 第二个副本放置在与第一个节点不同的机架中的节点中,保证机架间的高可用。
  • 第三个有不同机房则跨机房随机放置在某个节点上;只有一个机房则和第二副本在同一个机架,随机放在不同的节点中。
  • 更多的副本,则继续随机放置,需要注意的是一个节点最多放置一个副本。

HDFS 读流程中如何找到最佳节点? 这个放置策略其实也就是上一篇中提到的 HDFS 读流程中如何找到最佳节点的答案。读的过程,会首先找离 Client 最近的 DataNode,保证读的高效避免资源浪费,先后顺序依次是:

  1. 与 Client 在同一服务器
  2. 在同一机架
  3. 在同一个机房
  4. 跨机房

“随机放置”的规则? 上面提到了对于同机架的不同节点执行“随机放置”,然而“随机放置”也不是完全的随机,也是有规则的,具体需要做如下的判断。

  • storage 的存储类型是要求给定的存储类型
  • storage 不能是 READ_ONLY 只读的
  • storage 不能是坏的
  • storage 所在机器不应该是已下线或下线中的节点
  • storage 所在节点不应该是旧的,一段时间内没有更新心跳的节点
  • 节点内保证有足够的剩余空间能满足写 Block 要求的大小
  • 要考虑节点的 IO 负载繁忙程度
  • 要满足同机架内最大副本数的限制

短路读机制 Short Circuit Local Reads

上一篇已经提到了 HDFS 读取数据的时候 Client 端是需要和 DataNode 进行交互,由 DataNode 返回数据,这似乎是一个常规的流程,但是如果数据和 Client 在同一台服务器,仍然需要通过 TCP 套接字连接到 DataNode,然后进行数据传输的话,就会显得没有那么高效了。

2-4.jpg

短路读机制使 Client 端和目标 DataNode 在同一台服务器时,可以直接从本地磁盘读取数据,不需要通过 DataNode 中转数据。为了解决权限的问题,HDFS 采用了 Unix 的一种机制:文件描述符传递。如图,DFSClient 发起读请求后,DataNode 不是将数据目录传递给 DFSClient,而是打开块文件和元数据文件,并将它们的文件描述符传递给 DFSClient,DFSClient 再根据文件描述符直接从磁盘读取数据。

文件描述符实际上是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。Unix 和 Windows 系统都允许在进程间传递文件描述符。

短路读机制是如何保证文件的安全性的?

  • 文件描述符是只读的,DFSClient 无法修改传递描述符的文件。
  • DFSClient 只能访问文件描述符指向的文件,对其他文件和目录没有访问权限。

其他面试题

HDFS 在设计上是如何避免 NameNode 成为数据读写瓶颈的? 在设计上比较重要的点是客户端直接从 DataNode 上检索数据, NameNode 只负责告知需要检索的 DataNode,不负责实际数据的中转。这种设计成功避免了 NameNode 成为读写的瓶颈,能承受高并发请求,因为读数据是客户端与集群各个 DataNode 之间的操作,这期间,NameNode 仅仅只需返回在内存中的块位置信息。这道题考察的是对 NameNode 作用的理解,它仅仅只作为一个存储元数据的中转站,不负责数据的实际读写。

数据写入时各个 DataNode 时如何保证数据一致的? PipeLine 写入,写入完成返回 ack 信息,DataNode 完成数据量达到配置的阈值则视为成功,若返回成功后某数据副本存在异常则 NameNode 会做 DataNode 间数据同步的收尾工作。这道题考察的是 DataNode 之间的数据同步机制,写入成功数阈值可配置,关键在于 NameNode 的收尾工作。

HDFS 特性 考察的是对 HDFS 场景的理解,比较基础。

  • 高可用,上面的内容也多次提到了这一点。HDFS 设计的重点是支持高吞吐量的数据访问,而不是低延迟的数据访问; HDFS 适合于大文件的存储,文档的大小应该是是 GB 到 TB 级别的。HDFS 具有良好的跨平台移植性,使很多大数据组件都依赖它来做底层存储。
  • 不适合低延迟数据访问场景,不支持随机读写;不适合小文件存取场景;不支持单个文件的并发写入;不支持文件修改场景。

Hadoop 的压缩格式?和各自的优缺点

压缩格式可分割性native压缩率(相对而言)速度(相对而言)linux 命令其他
gzip只用于冷数据
bzip2支持HBase 不支持
lzo支持可用于热数据,Hadoop 最常用的压缩格式
snappy可用于热数据

HDFS 为何不适合小文件存储?如何解决? 小文件过多,就意味着 Block 会很多,对于元数据来说,不管存储的实际文件有多大,一个 block 元数据的大小都是在 150byte 左右。同时,元数据信息都是存储在 NameNode 的,活跃的 NameNode 是单节点的,这样会导致 NameNode 内存消耗过大,成为集群瓶颈。另外文件过小,寻道时间大于数据读写时间,这是非常低效的表现。**

  • 事后解决:即小文件合并成大文件,可以使用 hadoop archive 命令将文件合并为 har 文件
  • 从根源解决:注意依赖于 HDFS 存储的数据写入,通过 SequenceFile 合并小文件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老蒙大数据

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值