HDFS面试题汇总大全

1 HDFS 1.0 架构

在这里插入图片描述
NameNode
NameNode 负责管理整个分布式系统的元数据,主要包括:

  • 目录树结构;
  • 文件到 Block 的映射关系;
  • Block 副本及其存储位置等管理数据;
  • DataNode 的状态监控,两者通过心跳来传递管理信息和数据信息,通过这种方式的信息传递,NameNode 可以获知每个 DataNode 保存的 Block 信息、DataNode 的健康状况、命令 DataNode 启动停止等(如果发现某个 DataNode 节点故障,NameNode 会将其负责的 block 在其他 DataNode 上进行备份)。

这些数据保存在内存中,同时在磁盘保存两个元数据管理文件:fsimage 和 editlog。这两个文件相结合可以构造完整的内存数据。

  • fsimage:是内存命名空间元数据在外存的镜像文件;
  • editlog:则是各种元数据操作的 write-ahead-log 文件,在体现到内存数据变化前首先会将操作记入 editlog 中,以防止数据丢失。

Secondary NameNode
Secondary NameNode 并不是 NameNode 的热备机,而是定期从 NameNode 拉取 fsimage 和 editlog 文件,并对两个文件进行合并,形成新的 fsimage 文件并传回 NameNode,这样做的目的是减轻 NameNode 的工作压力,本质上 SNN 是一个提供检查点功能服务的服务点。

DataNode
负责数据块的实际存储和读写工作,Block 默认是64MB(HDFS2.0改成了128MB),当客户端上传一个大文件时,HDFS 会自动将其切割成固定大小的 Block,为了保证数据可用性,每个 Block 会以多备份的形式存储,默认是3份。

缺陷:

  • NameNode 的单点问题,如果 NameNode 挂掉了,数据读写都会受到影响,HDFS 整体将变得不可用,这在生产环境中是不可接受的;
  • 水平扩展问题,随着集群规模的扩大,1.0 时集群规模达到3000时,会导致整个集群管理的文件数目达到上限(因为 NameNode 要管理整个集群 block 元信息、数据目录信息等)。

为了解决上面的两个问题,Hadoop2.0 提供一套统一的解决方案:

  • HA(High Availability 高可用方案):这个是为了解决 NameNode 单点问题;
  • NameNode Federation:是用来解决 HDFS 集群的线性扩展能力。

2 HDFS写数据流程

  • 1.客户端向NameNode发出写文件请求,通过RPC与NameNode建立通信。

  • 2.namenode收到客户端的请求后,首先会检测元数据的目录树;检查权限并判断待上传的文件是否已存在,如果已存在,则拒绝client的上传。如果不存在,则响应客户端可以上传。
    (注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功)

  • 3.客户端收到可以上传的响应后,会把待上传的文件切块(hadoop2.x默认块大小为128M);然后再次给namenode发送请求,上传第一个block块。

  • 4.namenode收到客户端上传block块的请求后,首先会检测其保存的datanode信息,确定该文件块存储在哪些节点上;最后,响应给客户端一组datanode节点信息。

  • 5.客户端根据收到的datanode节点信息,首先就近与某个datanode节点例如A建立网络连接,本质上就是RPC调用,建立pipeline,A收到请求后会继续调用B,B会继续调用C,将整个pipeline建立完成,连通后逐级返回确认信息给客户端,表示通道已连通,可以传输数据。

  • 6.客户端收到确认信息后,开始向A上上传第一个block(先从磁盘读取数据后放到本地缓存),以packet(数据包,64kb)为单位,A收到一个packet就会发送给B,然后B发送给C。
    (注:并不是写好一个块或一整个文件后才向后分发)
    每个DataNode写完一个块后,会返回确认信息。
    (注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生。pipeline正向传输的是数据流,反向传输的是ack确认)

  • 7.第一个block块写入完毕,若客户端还有剩余的block未上传;则客户端会从(3)开始,继续执行上述步骤;直到整个文件上传完毕。
    写完数据,关闭输输出流。
    发送完成信号给NameNode。
    (注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报。最终一致性则其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性)

3 HDFS读数据流程

HDFS 文件读取过程

其具体过程总结如下(简单总结一下):

  • Client 通过 DistributedFileSystem 对象与集群的 NameNode 进行一次 RPC 远程调用,获取文件 block 位置信息;
  • NameNode 返回存储的每个块的 DataNode 列表;
  • Client 将连接到列表中最近的 DataNode;
  • Client 开始从 DataNode 并行读取数据;
  • 一旦 Client 获得了所有必须的 block,它 就会将这些 block 组合起来形成一个文件。
    在处理 Client 的读取请求时,HDFS 会利用机架感知选举最接近 Client 位置的副本,这将会减少读取延迟和带宽消耗。

4 HDFS2.0 高可用

在这里插入图片描述
HDFS 高可用架构主要由以下组件所构成:

  • Active NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。
  • 主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。
  • Zookeeper 集群:为主备切换控制器提供主备选举支持。
  • 共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和 NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。
  • DataNode 节点:除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。

5 HDFS HA中的共享存储如何实现

NameNode的共享存储方案有很多,比如Linux HA,WMware FT, QJM等,基于QJM的共享存储已经成为默认实现。

基于QJM 的共享存储系统主要用于保存EditLog,并不保存FSImage 文件。FSImage 文件还是在NameNode 的本地磁盘上。QJM 共享存储的基本思想来自于Paxos 算法,采用多个称为JournalNode 的节点组成的JournalNode 集群来存储EditLog。每个JournalNode保存同样的EditLog 副本。每次NameNode 写EditLog 的时候,除了向本地磁盘写入EditLog 之外,也会并行地向JournalNode 集群之中的每一个JournalNode 发送写请求,只要大多数(majority) 的JournalNode 节点返回成功就认为向JournalNode 集群写入
EditLog 成功。如果有2N+1 台JournalNode,那么根据大多数的原则,最多可以容忍有N台JournalNode 节点挂掉。
在这里插入图片描述

6 NameNode 主备切换

在这里插入图片描述

  • 1,HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测。

  • 2,HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFailoverController 注册的相应方法进行处理。

  • 3,如果 ZKFailoverController 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举。

  • 4,ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举。

  • 5,ActiveStandbyElector 在主备选举完成后,会回调 ZKFailoverController 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。

  • 6,ZKFailoverController 调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。

7 HDFS 2.0 Federation 实现

在这里插入图片描述
Federation 的核心思想是将一个大的 namespace 划分多个子 namespace,并且每个 namespace 分别由单独的 NameNode 负责,这些 NameNode 之间互相独立,不会影响,不需要做任何协调工作(其实跟拆集群有一些相似),集群的所有 DataNode 会被多个 NameNode 共享。

其中,每个子 namespace 和 DataNode 之间会由block pools建立映射关系,block pools由若干pool构成,一个子 namespace 可以对应1个pool,一个pool可以对应多个DataNode。每个 DataNode 需要向集群中所有的 NameNode 注册,且周期性地向所有 NameNode 发送心跳和块报告,并执行来自所有 NameNode 的命令。

  • 一个 block pool 由属于同一个 namespace 的数据块组成,每个 DataNode 可能会存储集群中所有 block pool 的数据块;
  • 每个 block pool 内部自治,也就是说各自管理各自的 block,不会与其他 block pool 交流,如果一个 NameNode 挂掉了,不会影响其他 NameNode;
  • 某个 NameNode 上的 namespace 和它对应的 block pool 一起被称为 namespace volume,它是管理的基本单位。当一个 NameNode/namespace 被删除后,其所有 DataNode 上对应的 block 也会被删除,当集群升级时,每个 namespace volume 可以作为一个基本单元进行升级。

8 HDFS 脑裂问题

脑裂(split-brain),指在一个高可用(HA)系统中,当联系着的两个节点断开联系时,本来为一个整体的系统,分裂为两个独立节点,这时两个节点开始争抢共享资源,结果会导致系统混乱,数据损坏。比如NameNode 可能会出现这种情况,NameNode 在垃圾回收(GC)时,可能会在长时间内整个系统无响应,因此,也就无法向 zk 写入心跳信息,这样的话可能会导致临时节点掉线,备 NameNode 会切换到 Active 状态,这种情况,可能会导致整个集群会有同时有两个 NameNode,这就是脑裂问题。

zookeeper社区对这种问题的解决方法叫做fencing,中文翻译为隔离,也就是想办法把旧的active namenode隔离起来,使它不能正常对外提供服务。

进行fencing的时候会执行以下操作:

(1)首先尝试调用这个旧的active NameNode的哈HAServiceProtocol RPC接口的transitionToStandby方法,看能不能把它转换为Standby状态。
(2)如果transitionToStandby方法调用失败,那么就执行Hadoop配置文件之中预定义的隔离措施,Hadoop目前主要提供两种隔离措施,通常会选择sshfence:

  • sshfencing:通过ssh登录到目标主机上,执行命令fuser将对应的进程杀死
  • shellfencing:执行一个用户自定义的shell脚本来将对应的进程隔离。

9 QJM 设计

在这里插入图片描述

10小文件过多会有什么危害,如何避免

Hadoop上大量hdfs元数据信息存储在NameNode内存中,因此过多的小文件必定会压垮NameNode的内存。
显而易见的解决方案就是合并小文件,可以选择在客户端上传时执行一定的策略先合并,或者是使用Hadoop的CombineFileInputFormat<K,V>实现小文件的合并。

11 HDFS在读取文件的过程中,如果其中一个快突然损坏了怎么办

客户端读取完DataNode 上的块之后会进行checksum 验证,也就是把客户端读取到本地的块与HDFS 上的原始块进行校验,如果发现校验结果不一致,客户端会通知NameNode,然后再从下一个拥有该block 副本的DataNode 继续读。

12 HDFS 在上传文件的时候,如果其中一个DataNode 突然挂掉了怎么办?

客户端上传文件时与DataNode 建立pipeline管道,管道正向是客户端向DataNode发送的数据包,管道反向是DataNode 向客户端发送ack 确认,也就是正确接收到数据包之后发送一个已确认接收到的应答,当DataNode 突然挂掉了,客户端接收不到这个DataNode 发送的ack 确认,客户端会通知NameNode,NameNode 检查该块的副本与规定的不符,NameNode 会通知DataNode 去复制副本,并将挂掉的DataNode 作下线处理,不再让它参与文件上传与下载。

13 NameNode在启动的时候会做哪些操作

首次启动NameNode。

  1. 格式化文件系统,为了生成hsimage文件
  2. 启动NameNode
    2.1 读取fsimage文件,将内容加载进内存
    2.2 等待DataNode注册与发送block report
  3. 启动DataNode
    3.1 向NameNode注册
    3.2 发送block report
    3.3 检查fsimage 中记录的块的数量和block report 中的块的总数是否相同
  4. 对文件系统进行操作(创建目录,上传文件,删除文件等)
    4.1 此时内存中已经有文件系统改变的信息,但是磁盘中没有文件系统改变的信息,此时会将这些改变信息写入edits 文件中,edits 文件中存储的是文件系统元数据改变的信息。

第二次启动NameNode

  1. 读取fsimage 和edits 文件
  2. 将fsimage 和edits 文件合并成新的fsimage 文件
  3. 创建新的edits 文件,内容为空
  4. 启动DataNode

14 HDFS的优点

  • 高吞吐量访问:HDFS的每个Block分布在不同的Rack上,在用户访问时,HDFS会计算使用最近和访问量最小的服务器给用户提供。由于Block在不同的Rack上都有备份,所以不再是单数据访问,所以速度和效率是非常快的。另外HDFS可以并行从服务器集群中读写,增加了文件读写的访问带宽。
  • 高容错性:系统故障是不可避免的,如何做到故障之后的数据恢复和容错处理是至关重要的。HDFS通过多方面保证数据的可靠性,多份复制并且分布到物理位置的不同服务器上,数据校验功能、后台的连续自检数据一致性功能都为高容错提供了可能。
  • 线性扩展:因为HDFS的Block信息存放到NameNode上,文件的Block分布到DataNode上,当扩充的时候仅仅添加DataNode数量,系统可以在不停止服务的情况下做扩充,不需要人工干预。

15 HDFS故障检测机制

  • 针对节点失败问题,,主要指DataNode失效,HDFS使用了心跳机制,DataNode定期向NameNode发送心跳信息,NameNode根据心跳信息判断DataNode是否存活;
  • 针对网络故障而导致无法收发数据的问题,HDFS提供了ACK的机制,在发送端发送数据后,如果没有收到ACK并且经过多次重试后仍然如此,则认为网络故障;
  • 针对数据损坏问题,所有DataNode会定期向NameNode发送自身存储的块清单,在传输数据的同时会发送总和校验码,NameNode依次来判断数据是否丢失或损坏。

16 容错机制

读容错
由于在读HDFS的过程中会从NameNode获取到数据块位置列表,如果某个DataNode失效,换个DataNode读即可。

写容错
写HDFS的过程中会对多个DataNode建立管道进行写入,如果数据发送者没有收到其中某个DataNode的ACK,则认为该DataNode失效,会跳过该DataNode并将数据写入剩余DataNode。NameNode收集DataNode信息时发现文件的副本数与设置值不一致,会重新寻找一个DataNode保存副本。

DataNode失效
在NameNode中会持有数据块表和DataNode两张表。数据块表存储着某个数据块(包括副本)所在的DataNode,DataNode表存储着每个DataNode中保存的数据块列表。由于DataNode会周期性地给NameNode发送自己所持有的数据块信息,因此NameNode会持续更新数据块表和DataNode表。如果发现某个DataNode上的数据块错误,NameNode会从数据块表删除该数据块;如果发现某个DataNode失效,NameNode会对两张表进行更新。NameNode还会周期性地扫描数据块表,如果发现数据块表中某个数据库的备份数量低于所设置的备份数,则会协调从其它DataNode复制数据到另一个DataNode上完成备份。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值