HDFS 是一个分布式文件系统,它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS 上读写文件的过程与我们平时使用的单机文件系统非常不同,本文就介绍 HDFS 上读写文件过程。

一、写文件过程

在 HDFS 文件系统上创建并写一个文件,流程如下图所示:

hdfs-write-flow

具体过程描述如下:

  1. Client 调用 DistributedFileSystem 对象的 create 方法,创建一个文件输出流(FSDataOutputStream)对象
  2. 通过 DistributedFileSystem 对象与 Hadoop 集群的 NameNode 进行一次RPC远程调用,在HDFS的 Namespace 中创建一个文件条目(Entry),该条目没有任何的 Block
  3. 通过 FSDataOutputStream 对象,向 DataNode 写入数据,数据首先被写入 FSDataOutputStream 对象内部的 Buffer 中,然后数据被分割成一个个 Packet 数据包
  4. 以Packet最小单位,基于 Socket 连接发送到按特定算法选择的 HDFS 集群中一组 DataNode(正常是3个,可能大于等于1)中的一个节点上,在这组 DataNode 组成的 Pipeline 上依次传输 Packet
  5. 这组 DataNode 组成的 Pipeline 反方向上,发送 ack ,最终由 Pipeline 中第一个 DataNode 节点将 Pipeline ack 发送给 Client
  6. 完成向文件写入数据,Client 在文件输出流(FSDataOutputStream)对象上调用 close 方法,关闭流
  7. 调用 DistributedFileSystem 对象的 complete 方法,通知 NameNode 文件写入成功

Packet结构与定义

Client 向 HDFS 写数据,数据会被组装成 Packet,然后发送到 Datanode 节点。Packet 分为两类,一类是实际数据包,另一类是 heatbeat 包。

packet 相关参数如下:

参数名称 参数值 参数含义
chunkSize 512+4=516 每个chunk的字节数(数据+校验和)
csize 512 每个chunk数据的字节数
psize 64*1024 每个packet的最大字节数(不包含header)
DataNode.PKT_HEADER_LEN 21 每个packet的header的字节数
chunksPerPacket 127 组成每个packet的chunk的个数
packetSize 25+516*127=65557 每个packet的字节数(一个header+一组chunk)

Packet数据包的组成结构,如图所示:

hdfs-packet-structure

二、读文件过程

在 HDFS 文件系统上读取一个文件,流程如下图所示:

hdfs-read-flow

  1. Client 调用 DistributedFileSystem 对象的 open 方法,创建一个文件输入流(FSDataInputStream)对象
  2. 通过 DistributedFileSystem 对象与 Hadoop 集群的 NameNode 进行一次RPC远程调用,确定需要打开的文件一批数据块的存储位置
  3. 通过 FSDataInputStream 对象,读取距离客户端最近的 datanode,该 datanode 读取完成后接着寻找下一个 datanode 节点并读取数据
  4. 继续询问 namenode 下一批数据块的 datanode 的位置
  5. 读取完成后调用 FSDataInputStream 的 close 方法结束整个流程