基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

描述一下HDFS读数据的完整流程

知识点图片

HDFS(Hadoop Distributed File System)的读数据流程是一个经典的分布式系统交互过程。整个流程的设计核心是:“控制流(元数据)走 NameNode,数据流走 DataNode”,以此来减轻单点 NameNode 的压力。

以下是 HDFS 读取数据的完整流程,按步骤详细分解:

核心组件角色

  • Client(客户端):发起读请求,拼接最终数据。
  • NameNode(NN):管理元数据,知道文件被切分成了哪些 Block,以及这些 Block 存在哪些 DataNode 上。
  • DataNode(DN):实际存储数据块(Block)的节点。

完整图文步骤解析

第一步:客户端发起打开文件请求

  1. 客户端应用程序调用 FileSystem 对象的 open() 方法(在 HDFS 中通常是 DistributedFileSystem 实例)来打开目标文件。

第二步:NameNode 解析并返回区块位置(获取元数据)

  1. DistributedFileSystem 通过 RPC(远程过程调用) 联系 NameNode。
  2. NameNode 收到请求后,会进行一系列检查:
    • 检查该文件是否存在。
    • 检查客户端是否有权限读取该文件。
  3. 检查通过后,NameNode 会查询元数据,获取该文件前几个 Block 的存储位置(也就是哪些 DataNode 上有这些 Block 的副本)。
  4. 距离排序:NameNode 返回的 DataNode 列表并非随机,而是根据网络拓扑结构(机架感知计算),按距离客户端由近到远进行排序。如果客户端本身就是一个 DataNode,那么优先返回本地的副本位置(这就是常说的“数据本地化”)。
  5. NameNode 向客户端返回一个支持文件定位的输入流对象 FSDataInputStream(其底层包装了 DFSInputStream 对象),供客户端读取数据。

第三步:客户端连接 DataNode 准备读取

  1. 客户端调用输入流 FSDataInputStreamread() 方法。
  2. DFSInputStream 会找出距离最近的 DataNode(针对第一个 Block),并与之建立 socket 连接。

第四步:数据流式传输(核心读取过程)

  1. 数据开始从 DataNode 源源不断地流式(Stream)传输到客户端。
  2. 客户端以数据包(Packet)为单位接收数据,并校验数据的完整性(Checksum)。
  3. 当这个 Block 的数据读取完毕后,DFSInputStream 会关闭与这个 DataNode 的连接。

第五步:循环读取后续 Block

  1. 客户端继续读取下一个 Block。DFSInputStream 会寻找下一个 Block 的最佳 DataNode,并重复步骤 3 和 4。
  2. 分批获取元数据:如果在第二步中,NameNode 只返回了文件部分 Block 的位置(文件很大的情况),当客户端读完这些 Block 后,DFSInputStream 会向 NameNode 发起第二次 RPC 请求,获取下一批 Block 的位置信息,然后继续读取。
  3. 在整个过程中,对于客户端的代码来说,它感觉就像是在读取一个连续的本地大文件,底层的跨网络、跨节点切换对用户是透明的。

第六步:关闭连接

  1. 当文件所有数据读取完毕后,客户端调用 FSDataInputStreamclose() 方法,关闭输入流,释放资源。

流程图解(简易版)

plaintext
  Client                                NameNode                              DataNode
    |                                      |                                      |
    |--- 1. open(filePath) --------------->|                                      |
    |                                      | (检查权限/文件存在性)                |
    |<-- 2. 返回 Block 位置列表 (按距离排序)-|                                      |
    |                                      |                                      |
    |--- 3. read() / 连接最近的 DN ---------------------------------------------->|
    |                                      |                                      |
    |<-- 4. 流式传输数据块 (Block 1) ---------------------------------------------|
    |                                      |                                      |
    |--- 5. 连接最近的 DN 读取下一个 Block -------------------------------------->|
    |<-- 6. 流式传输数据块 (Block 2) ---------------------------------------------|
    |                                      |                                      |
    | (若元数据耗尽,再次向NN请求后续Block)  |                                      |
    |--- 7. 请求后续 Block 位置 ---------->|                                      |
    |<-- 8. 返回后续 Block 位置 -----------|                                      |
    |                                      |                                      |
    |--- 9. close() -----------------------|--------------------------------------|

关键机制与容错处理(面试高频考点)

在实际读取过程中,网络和节点不可能总是完美的,HDFS 设计了完善的容错机制:

  1. 节点故障(DataNode 宕机或网络不通)

    • 如果客户端在读取过程中与某个 DataNode 通信中断,或者连接失败。
    • 客户端会把这个有故障的 DataNode 记录下来(防止后续再去请求它)。
    • 客户端会从该 Block 的副本列表中取出下一个距离最近的 DataNode 进行连接并继续读取。
  2. 数据损坏(Checksum 校验失败)

    • HDFS 的 DataNode 在存储 Block 时会同时存储校验和(Checksum)。
    • 客户端在读取数据时会进行本地校验。如果发现读取的数据和校验和不匹配,说明数据已损坏。
    • 客户端会向 NameNode 汇报这个损坏的 Block,以便 NameNode 后续安排重新复制健康副本。
    • 同时,客户端会默默地去连接该 Block 的另一个健康副本节点读取数据,整个过程对上层应用不报错。
  3. 短路读取(Short-Circuit Local Read)

    • 优化机制:如果客户端正好与包含该数据的 DataNode 运行在同一台物理机器上。
    • 客户端将不再通过 TCP Socket 穿透网络栈去读取,而是绕过 DataNode 进程,直接读取本地操作系统文件系统上的数据文件。这极大地提高了读取性能。
00:00
00:00