HDFS 的架构和读写流程

HDFS 的架构

  NameNode :负责文件元数据信息的操作以及处理客户端的请求。
  DataNode:负责存储实际的数据块,执行数据块的读/写操作。
  SecondaryNameNode:保存 namenode 中对 HDFS metadata 的信息的备份,并减少 namenode 重启的时间。
HDFS 的架构和读写流程

HDFS读写数据流的流程

文件写入
  1、客户端对 DistributedFileSystem 对象调用create() 。
  2、DistributedFileSystem 请求 NameNode,NameNode返回是否可以上传。
  3、DistributedFileSystem 向客户端返回 FSDataOutputStream对象( FSDataOutputStream对象封装了一个DFSOutputStream对象,该对象负责处理namenode和datanode之间的通信),客户端对 FSDataOutputStream对象写入数据。
  4、DFSOutputStream将它分成一个个的数据包,并写入内部队列(数据队列),由 DataStreamer挑选出适合存储副本的一组datanode,并据此向namenode请求分配新的数据块来存储数据队列 —— 假设复本数为3,管线中就有3个节点(dn1、dn2、dn3),DataStreamer将数据包流式传输到管道中的各个节点,各datanode节点接收存储数据包。(数据队列: dn1 -> dn2 -> dn3)
  5、将数据包传输到管道的最后一个datanode后,由DFSOutputStream维护的内部数据包队列(确认队列)来确认datanode的回执,收到管道中所有datanode确认信息后,该数据包才会从确认队列删除(确认队列:dn3 -> dn2 -> dn1)
  6、客户端完成数据写入后,对FSDataOutputStream对象调用close()方法,将剩余数据包全部写入datanode管线,并等待确认信息。
  7、最后告知namenode文件写入完成。
HDFS 的架构和读写流程

  namenode如何选择在哪个datanode存储复本(replica)?
    Hadoop的默认布局策略是在运行客户端的节点上放第一个复本(如果客户端运行在集群之外,就随机选择一个节点,不过系统会避免挑选那些存储太慢或太忙的节点)。第二个复本放在与第一个不同且随机另外选择的机架中节点上(离架)。第三个复本与第二个复本放在同一个机架上,且随机选择另一个节点。其他复本放在集群中随机选择的节点上,不过系统会尽量避免在同一个机架上放太多复本。

  如果datanode在写入时发生故障
    1) 关闭管线,把队列中的所有数据包(共同组成一个块)添加回数据队列的最前端,确保下游的datanode不漏掉任何一个数据包。
    2) 将存储了正确数据块信息的datanode添加标识,把标识传给namenode,故障节点在恢复后删除存储的部分数据块,在管线添加一个新的datanode,替换故障datanode。

文件读取
  1、客户端调用FileSystem的open()方法打开文件,对于HDFS,是一个DistributedFileSystem的实例。
  2、 DistributedFileSystem的实例通过RPC调用namenode,namenode根据映射关系返回存有文件块副本的datanode地址,datanode根据与客户端的距离排序(网络拓扑),如果本身也是datanode且存有文件块,则客户端从本地获取副本。
  3、 DistributedFileSystem返回一个FSDataInputStream对象(一个支持文件定位的数据流)给客户端以便读取数据,FSDataInputStream封装了DFSInputStream,这个类管理者datanode和namenode的I/O,客户端对DFSInputStream反复调用read()方法,将数据从datanode传输到客户端。
  4、 块读取完毕后,DFSInputStream关闭与该datanode的连接,寻找下一个块所在的最佳datanode,重复读取,一直到读取完毕,调用FSDataInputStream的close()。
HDFS 的架构和读写流程
  客户端通过NameNode找到文件块所在的DataNode地址,然后从DataNode读取数据。这个设计重点是,namenode告知客户端每个块中最佳的datanode,并让客户端直接连接到该datanode检索数据。由于数据流分散在集群中的所有datanode,所以这种设计能使HDFS可扩展到大量的并发客户端。同时,namenode只需要响应块位置的请求(这些信息存储在内存中,因而非常高效),无需响应数据请求,否则随着客户端数量的增长,namenode会很快成为瓶颈。