第 4 章 HDFS 的读写流程

4.1 HDFS 写数据流程

4.1.1 剖析文件写入

Gg8q.png

  1. 客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件,通过RPC与NameNode建立通信

  2. NameNode 检查目标文件是否已存在,父目录是否存在,如果这两者有任意一个不满足,则直接报错,如果两者都满足,则返回给客户端一个可以上传的信息;

  3. Client根据文件的大小进行切分,默认128M一块,切分完成之后给NameNode发送请求第一个block块上传到哪些服务器上;

  4. NameNode收到请求之后,根据网络拓扑和机架感知以及副本机制进行文件分配,返回可用的DataNode的地址。图中NameNode 返回 3 个 DataNode 节点,分别为 dn1、dn2、dn3;

    注:Hadoop在设计时考虑到数据的安全与高效, 数据文件默认在HDFS上存放三份, 存储策略为本地一份,同机架内其它某一节点上一份, 不同机架的某一节点上一份

  5. 客户端通过 FSDataOutputStream 模块请求 dn1 上传数据,本质上就是RPC调用,dn1 收到请求会继续调用 dn2,然后 dn2 调用 dn3,将这个通信管道(pipeline)建立完成。

  6. dn1、dn2、dn3 逐级应答客户端;

  7. 客户端开始往 dn1 上传第一个 Block(先从磁盘读取数据放到一个本地内存缓存), 以packet(数据包,64kb)为单位,dn1 收到一个 packet就会传给 dn2,dn2 传给 dn3;dn1 每传一个 packet 会放入一个应答队列等待应答

    (数据被分割成一个个的packet数据包在pipeline上依次传输,在pipeline反向传输中,逐个发送ack(命令正确应答),最终由pipeline中第一个DataNode节点A将pipelineack发送给Client)

  8. 当一个block传输完成之后, Client再次请求NameNode上传第二个block,NameNode重新选择三台DataNode给Client(重复执行 3-7 步)

4.1.2 网络拓扑-节点距离计算

在 HDFS 写数据的过程中,NameNode 会选择距离待上传数据最近距离的 DataNode 接 收数据。那么这个最近距离怎么计算呢?

节点距离:两个节点到达最近的共同祖先的距离总和。

GkZE.png

例如,假设有数据中心 d1 机架 r1 中的节点 n1。该节点可以表示为/d1/r1/n1。利用这种 标记,这里给出四种距离描述:

  • Distance(/d1/r1/n0, /d1/r1/n0)=0(同一节点上的进程)

  • Distance(/d1/r2/n0, /d1/r3/n2)=4(同一数据中心不同机架上的节点)

  • Distance(/d1/r1/n1, /d1/r1/n2)=2(同一机架上的不同节点)

  • Distance(/d1/r2/n1, /d2/r4/n1)=6(不同数据中心的节点)

4.1.3 机架感知(副本存储节点选择)

机架感知说明

(1)官方说明 http://hadoop.apache.org/docs/r3.1.3/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication

For the common case, when the replication factor is three, HDFS’s placement policy is to put one replica on the local machine if the writer is on a datanode, otherwise on a random datanode, another replica on a node in a different (remote) rack, and the last on a different node in the same remote rack. This policy cuts the inter-rack write traffic which generally improves write performance. The chance of rack failure is far less than that of node failure; this policy does not impact data reliability and availability guarantees. However, it does reduce the aggregate network bandwidth used when reading data since a block is placed in only two unique racks rather than three. With this policy, the replicas of a file do not evenly distribute across the racks. One third of replicas are on one node, two thirds of replicas are on one rack, and the other third are evenly distributed across the remaining racks. This policy improves write performance without compromising data reliability or read performance.

(2)源码说明 Crtl + n 查找 BlockPlacementPolicyDefault,在该类中查找 chooseTargetInOrder 方法。

GNqA.png

4.2 HDFS 读数据流程

GXYX.png

  1. 客户端通过 DistributedFileSystem 向 NameNode 请求下载文件(RPC请求),NameNode 通过查 询元数据,找到文件块所在的 DataNode 地址;
  2. NameNode收到请求之后会检查用户权限以及是否有这个文件,如果都符合,则会视情况返回部分或全部的block列表,对于每个block,NameNode都会返回含有该block副本的DataNode地址;这些返回的DataNode地址,会按照集群拓扑结构得出DataNode与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的DataNode状态为STALE,这样的排靠后;Client选取排序靠前的DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性);
  3. DataNode 开始传输数据给客户端(从磁盘里面读取数据输入流,以 Packet 为单位 来做校验)。底层上本质是建立Socket Stream(FSDataInputStream),重复的调用父类DataInputStream的read方法,直到这个块上的数据读取完毕;
  4. 客户端以 Packet 为单位接收,先在本地缓存,然后写入目标文件。

Q.E.D.


一蓑烟雨任平生