暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

HDFS 读写容错机制与调优技巧,你知道嘛?

小林玩大数据 2021-09-19
948
前言

大家好,我是林哥

在上一篇,HDFS 底层交换原理,看这篇就够了!文章中,已经聊了 HDFS
高可用架构、HDFS
源码级读写流程及可用性问题。今天接着上篇,继续跟大家聊聊 HDFS
读写失败场景下的容错机制和 HDFS
调优的一些技巧,希望给大家带来一点点启发!本篇文章概览如下:

文章概览

1.HDFS 读写异常的容错机制

Hadoop 的设计理念就是部署在廉价的机器上,因此在容错方面做了周全的考虑,主要故障包括 DataNode 宕机,网络故障和数据损坏。本文介绍的容错机制只考虑 HDFS 读写异常场景。

1.1 读数据异常场景处理

HDFS读流程

我们通过上图,简单回顾下 HDFS 的读数据流程,先打开文件,再调用read()
方法读取数据。

read()
方法中,调用了readWithStrategy()
方法读取DataNode
存储的数据。

  • readWithStrategy( )方法
readWithStrategy

readWithStrategy()
方法中使用 pos
控制数据的读取位置。

  • 首先,调用 blockSeekTo()
    方法获取一个保存了目标数据块的 DataNode
  • 其次,再调用 readBuffer()
    方法从获取到的 DataNode
    中读取数据

readWithStrategy()
方法实现可知,读失败场景比较简单。从上述代码 48 - 59 行可知,如果发生异常:

  1. 先把当前的异常节点放入 HashMap
    中,然后 DFSIputStream
    会尝试重新去连接列表里的下一个 DataNode
    ,默认重试 2 次。
  2. 同时,DFSInputStream
    还会对获取到的数据进行 checkSums
    核查,如果与存储在 NameNode
    的校验和不一致,说明数据块损坏,DFSInputStream
    就会试图从另一个拥有备份的 DataNode
    中去读取数据。
  3. 最后,NameNode
    会去同步异常数据块。

1.2 写数据异常场景处理

写流程

通过上图,简单回顾下写数据流程,客户端调用creat()
方法,通过 RPC 与 NameNode
通信,请求创建一个文件,之后调用write
,向数据流管道(Pipeline)写入数据。

写数据过程中以数据包(Packet)为单位,进行一个一个传输,数据包发送流程如下图:

数据包发送流程图

当构建完 DFSOutputStream 输出流时,客户端调用write()
方法把数据包写入 dataQueue 队列,在将数据包发送到 DataNode 之前,DataStreamer
会向 NameNode 申请分配一个新的数据块

然后,建立写这个数据块的数据流管道(pipeline),之后DataStreamer
会从 dataQueue
队列取出数据包,通过 pipeline 依次发送给各个 DataNode。

每个数据包(packet)都有对应的序列号,当一个数据块中所有的数据包都发送完毕,并且都得到了 ack 消息确认后,PacketProcessor
会将该数据包移出 ackQueue
,之后,Datastreamer
会将当前数据块的 pipeline 关闭。

通过不断循环上述过程,直到该文件(一个文件会被切分为多个Block
)的所有数据块都写完成。在数据块发送过程中,如果某台DataNode
宕机,HDFS
主要会做一下容错:

  1. 首先 pipiline
    被关闭,ackQueue
    队列中等待确认的 packet
    会被放入数据队列的起始位置不再发送,以防止在宕机的节点的下游节点再丢失数据。
  2. 然后,存储在正常的 DataNode
    上的 Block 块会被指定一个新的标识,并将该标识传递给 NameNode
    ,以便故障 DataNode
    在恢复后,就可以删除自己存储的那部分已经失效的数据块。
  3. 宕机节点会从数据流管道移除,剩下的 2 个好的 DataNode
    会组成一个新的 Pipeline
    ,剩下的 Block
    的数据包会继续写入新的 pipeline
    中。
  4. 最后,在写流程结束后,NameNode
    发现节点宕机,导致部分 Block
    块的备份数小于规定的备份数,此时 NameNode
    会安排节点的备份数满足 dfs.replication
    的配置要求。

以上过程,针对客户端是透明的。

2. HDFS 调优技巧

2.1 HDFS 小文件优化方法

HDFS
集群中 NameNode
负责存储数据块的元数据,其中包括文件名、副本数、文件的BlockId、以及Block 所在的服务器等信息,这个元数据的大小大约为 150 byte。

对于元数据来说,不管实际文件是大还是小,其大小始终在 150 byte 左右。如果 HDFS
存储了大量的小文件,会产生很多的元数据文件,这样便会导致NameNode
内存消耗过大;此外,元数据文件过多,使得寻址时间大于数据读写时间,这样显得很低效。

  • 数据源头解决:依赖于 HDFS
    存储的数据写入前,通过 SequenceFile 将小文件或小批数据合成大文件再上传到 HDFS
    上。
  • 事后解决:使用 Hadoop Archive
    归档命令,将已经存储在 HDFS
    上的多个小文件打包成一个 HAR 文件,即将小文件合并成大文件。

2.2 存储优化

纠删码存储

Hadoop 3.X 之前,数据默认以 3 副本机制存储,这样虽然提高了数据的可靠性,但所带来的是 200% 的存储开销。对于 I/O 频率较低的冷热数据集,在正常操作期间很少访问额外的块副本,但仍然消耗与第一个副本相同的资源量。

因此,一个自然的改进就是使用纠删码代替复制,它保证了相同级别的数据可靠性,存储空间却更少。它是将一个文件拆分成一些数据单元和一些校验单元。具体数据单元与校验单元的配比是根据纠删码策略确定的。

  • RS-3-2-1024K : 使用 RS 编码,每 3 个数据单元,生成 2 个校验单元,共 5 个单元,也就是说,这 5 个单元中,只要有任意的 3 个单元存在(无论是数据单元还是校验单元),就可以通过计算得到原始数据。每个单元的大小是 1024k。

此外,还有RS-10-4-1024k、RS-6-3-1024k、RS-LEGACY-6-3-1024k、XOR-2-1-1024k 这四种策略。所有的纠删码策略,只能在目录上设置。

默认情况下,所有内建的 EC 策略是不可用的,可以通过以下两种方式开启对纠删码策略的支持:

  1. 通过以下配置项,指定想要使用的 EC 策略。

  2. 开发人员还可以基于集群规模和期望的容错性,使用命令行的方式:hdfs ec -enablePolicy -policy [policyName]
    ,在集群上开启对某种纠删码策略的支持,policyName
    为纠删码策略名。

    之后,开发人员便可以通过 hdfs ec -setPolicy -path [directoryName] -policy [policyName]
    命令,实现对某个文件目录指定使用上述开启的 EC 策略了。如果缺少 [policyName]
    这个参数,集群会使用系统的默认值:RS-6-3-1024k

异构存储

异构存储是另外一种存储优化,主要解决不同的数据,存储在不同类型的硬盘中,以获取最佳性能。

  1. 存储类型:

    RAM_DISK:存储在内存镜像文件系统;

    SSD:SSD 固态硬盘

    DISK:普通磁盘存储,在 HDFS
    中,如果没有主动声明数据目录存储类型,默认都是 DISK

    ARCHIVE: 这个没有特指哪种存储介质,主要指的是计算能力比较弱而存储密度比较高的存储介质,用来解决数据量的容量扩增的问题,一般用于归档

  2. 存储策略:

Lazy_Persist:策略 ID 为15,它只有一个副本保存在内存中,其余副本都保存在磁盘中。

ALL_SSD:策略 ID 为12,其所有副本数都存在固态硬盘中。

One_SSD:策略 ID 为10,它有一个副本保存在固态,其余副本都保存在磁盘中

HOT(default):策略 ID 为7,所有副本都保存在磁盘中,这是默认的存储策略。

Warm:策略 ID 为5,一个副本在磁盘,其余副本都保存在归档存储上。

Cold:策略 ID 为2,所有副本都保存在归档存储上。

2.3 HDFS 调优参数

  1. NameNode
    内存生产配置

    HADOOP_NAMENODE_OPTS=-Xmx102400m
    ,Hadoop 3.x 中,其内存是动态分配的。

    cloudera 给出的经验值NameNode
    最小值 1G,每增加 100 万个 block
    增加 1G 值;

    DataNode
    最小值 4G,一个 DataNode
    上的副本总数低于 400 万,调为 4G,超 400 万,每增加 100 万,增加 1G。

  2. NameNode
    同时与 DataNode
    通信的线程数,即心跳并发配置(hdfs-site.xml)

    企业经验dfs.namenode.handler.count
    =20 × 𝑙𝑜𝑔 𝑒^𝐶𝑙𝑢𝑠𝑡𝑒𝑟 𝑆𝑖𝑧𝑒
    ,比如集群规模(DataNode 台 数)为 3 台时,此参数设置为 21

  3. DataNode
    进行文件传输时最大线程数(hdfs-site.xml)

  4. DataNode
    的最大连接数

    对于 DataNode 来说,如同 Linux 上的文件句柄的限制,当 DataNode上面的连接数超过配置中的设置时, DataNode就会拒绝连接,可以将其修改设置为65536。

  5. Hadoop 的缓冲区大小(core-site.xml)

  6. 开启回收站工作机制(core-sit.xml)

    开启回收站功能,可以将删除的文件在不超时的情况下恢复,起到防止误操作。

    注意:1.如果是在网页删除的文件,不会进入回收站                                  2.要求:fs.trash.checkpoint.interval
    <= fs.trash.interval


3. 高频面试题

  1. 客户端在写 DataNode
    的过程中,DataNode
    宕机是否对写有影响?
  2. 是否要完成所有目标 DataNode
    节点的写入,才算一次写成功操作?
  3. 读的过程如何保证数据没有被损坏,如果损坏如何处理?
  4. 交互过程数据校验的基本单位是什么?
  5. 数据写入各个 DataNode
    时如何保证数据一致性?
  6. 短路读机制
  7. 短路读机制是如何保证文件的安全性的?

参考资料

[1] https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-hdfs/HDFSErasureCoding.html

推荐阅读:

金九银十,校招简历该如何写,这篇文章告诉你答案!

HDFS 底层交互原理,看这篇就够了。


你好,我是林哥,某双一流研究生,互联网大厂大数据工程师,目前杭漂!非科班逆袭大厂!同时,我也是视频号玩家:小林玩大数据!分享大数据知识,逆袭经验!欢迎围观!

文章转载自小林玩大数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论