HDFS读写流程详解及故障处理机制

HDFS写数据流程

总体流程:

  客户端通过对DistributedFileSystem对象调用create()来新建文件,DistributedFileSystem对NamNode创建一个RPC调用,在文件系统的命名空间中新建一个文件,此时该文件中还没有相应的数据块,NamoNode执行各种不同的检查以确保这个文件不存在以及客户端有新建改文件的权限。
  如果这些检查均通过,NameNode就会为创建新文件记录一条记录,否则文件创建失败,并向客户端抛出一个IOException异常,DistributedFileySystem向客户端返回一个FSDataOutputStream对象。
  由此客户端可以开始写入数据,写入数据时,DFSOutputStream将它分成一个个的数据包(packet),并写入内部队列,称为"数据队列"。DataStreamer处理数据队列,它的责任是挑选出适合存储数据副本的一组DataNode,并要求NameNode分配数据块,这一组DataNode就构成了一个管线(假设副本数为3),即管线中有三个节点,DataStreamer将数据包流式传输到管线中第一个DataNode,该DataNode存储数据包并将它发送到管线中的第二个DataNode,同样,第二个再发给第三个。
  DFSOutputStream也维护这一个内部数据包队列来等待DataNode的收到确认回执,称为“确认队列”(ack queue)。收到管道中素有DataNode确认信息后,该数据包会从确认队列中删除。

HDFS读写流程详解及故障处理机制

步骤:

(1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。

(2)NameNode返回是否可以上传。

(3)客户端请求第一个 Block上传到哪几个DataNode服务器上。

(4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。

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

(6)dn1、dn2、dn3逐级应答客户端。

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

(8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。

故障处理

  如果DataNode在数据写入的时候发生率故障,首先它会关闭管线,确认把队列中的所有数据包都添加回数据队列的最前端,确保故障节点下游的DataNode不会漏掉数据包。并且为存储在另一个正常DataNode的当前数据块指定一个新的标识,并把该标识传给NameNode,以便故障的DataNode在恢复后可以删除存储的部分数据块。然后从管线中删除故障DataNode,基于另外两个正常的DataNode构建一条新的管线,剩下的数据块写入管线中正常的DataNode,当NameNode注意到快副本数量不足的时候,就会在另一个节点上创建一个新的副本,后续的数据块继续正常处理。


HDFS读流程

总体流程:

  客户端调用FileSystem对象的open()方法来打开希望读取的文件,对于HDFS来说,这个对象是DistributedFileSystem的一个实例。DistributedFileSystem通过远程调用(RPC)来调用NameNode,用来确定文件起始块的位置,对于每一个块,NameNode返回存有该块副本的DataNode地址。
  此外,这些DataNode根据他们与客户端的距离来排序(根据集群的网络拓扑),如果客户端本身就是一个DataNode,那么客户端就会从本地读取数据。
  接下来DistributedFileSystem类返回一个FSDataInputStream对象,给客户端用来读取数据,FSDataInputStream类转而封装DFSInputStream对象,该对象管理着DataNode和NameNode的I/O。
  接着客户端对这个输入流调用read()方法,存储着文件起始块的DataNode地址的DFSInputStream随即连接距离最近的文件中第一个块所在的DataNode,通过对数据流反复调用read()方法,可以将数据从DataNode传输到客户端,到达块的末端时,DFSInputStream关闭与该DataNode的连接,然后寻找下一个最佳的DataNode。
HDFS读写流程详解及故障处理机制

步骤:

(1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址.
(2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
(3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
(4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

故障处理

  读数据的时候,如果DFSInputStream在与DataNode通信时遇到了错误,就会试图从这个块的另外一个最邻近DataNode读取数据,它也会记住那个故障的DataNode,保证以后不会反复读取该节点上后续的块。DFSInputStream也会通过校验和确认从DataNode发来的数据是否完整,如果返现有损坏的块,DFSInputStream会试图从其他DataNode读取它的副本,也会将被损坏的块通知给NameNode。