文件读过程:

  • 客户端(client)用 FileSystem(HDFS 对应于 DistributedFileSystem)实例的 open 函数打开文件

  • FileSystem 用 RPC 调用 NameNode ,得到文件的 Blocks 信息,对于每一个 Block, NameNode 返回保存 Block 的DataNode 的地址,通过 FSDatalnputStream 封装。FSDatalnputStream 中进一步封装 DFSInputStream 对象,该对象主要用于与 NameNode 和 DataNode 通信。

  • 客户端调用 FSDatalnputStream 的 read 函数开始读取数据。

  • DFSInputStream 连接保存此文件第一个 Block 的最近的 DataNode,数据从 DataNode 读到客户端。在读取数据的过程中,如果客户端在与 DataNode 通信出现错误,则尝试连接包含此 Block 的下一个 DataNode 失败的DataNode 将被记录,以后不再连接。

  • 当此 Block 读取完毕时,DFSInputStream 关闭和此 DataNode 的连接,然后连接此文件下一个 Block 的最近的 DataNode。

  • 当客户端读取完毕数据的时候,调用 FSDatalnputStream 的 close 函数。

文件写过程:


  • 客户端通过对象 DistributedFileSystem 的 create 方法创建文件

  • DistributedFileSystem 创建一个RPC调用,申请在文件系统的命名空间中创建一个新的文件, 此时文件中还没有相应的数据块。若权限验证通过,返回一个 FSDataOutputStream 对象。

  • 客户端开始使用 FSDataOutputStream 对象写入数据。其中,FSDataOutputStream中包含一个DFSOutputStream对象,主要负责与 DataNode 和 NameNode 的通信。

  • DFSOutputStream 将数据分成数据包,写入 data queueo data queue 由 DataStreamer 读取,并通知 namenode分配 DataNode,用来存储数据块(每块默认复制 3 块)。分配的 DataNode 放在一个 pipeline 里。Data Streamer 将数据块写入 pipeline 中的第一个数据节点。第一个数据节点将数据块发送给第二个数据节点。第二个数据节点将数据发送给第三个数据节点。

  • DFSOutputStream 为发出去的数据块保存了ack queue,等待 pipeline 中的数据节点告知数据已经写入成功。如果 DataNode 在写入的过程中失败,关闭 pipeline,将 ack queue中的数据块放入 data queue 的开始,当前的Block 在已经写入的 DataNode 中被 NameNode 赋予新的标识,则错误节点重启后能够察觉其数据块是过时的,会被删除。失败的 DataNode 从 pipeline 中移除,另外的 Block 则写入 pipeline 中的另外两个 DataNode。NameNode 则被通知此 Block 是复制块数不足,将来会再创建第三份备份。

  • 最后通知 NameNode 写入完毕


最后修改: 2023年12月27日 星期三 17:19