详解hdfs读写文件流程

一.hdfs写数据流程

在这里插入图片描述
hdfs dfs -put 要上传的文件的路径 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(64KB)为单位,dn1收到一个packet就会传给
  • dn2,dn2传给 dn3;dn1 每传一个 packet 会放入一个应答队列等待应答。
  • 8.当一个block块传输完成之后,客户端再次请求NameNode上传第二个block的服务器,重复执行 3-7 步直到。

二.hdfs读数据流程

在这里插入图片描述
hdfs dfs -get 本地路径 hdfs文件系统路径

1.首先调用 FileSystem.open()方法,获取到 DistributedFileSystem 实例
2.DistributedFileSystem向Namenode发起RPC(远程过程调用)请求获得文件的开始部分或全部block列表,对于每个返回的块,都包含块所在的DataNode 地址,这些DataNode会按照Hadoop定义的集群拓扑结构得出客户端的距离,然后再进行排序.如果客户端本身就是一个
DataNode,那么他将从本地读取文件,这样会确保只读一份文件而不会去读取所有备份,而且距离是最短的
3.Distributed FileSystem会向客户端client返回一个支持文件定位的输入流对象FSDataInputStream,用于客户端读取数据。
FSDataInputStream包含一个DFSInputStream对象,这个对象用来管理DataNode和NameNode之间的I/O
4.客户端调用 read()方法,DFSInputStream 就会找出离客户端最近的datanode 并连接 datanode
5.DFSInputStream 对象中包含文件开始部分的数据块所在的 DataNode 地址,首先它会连接包含文件第一个块最近 DataNode。
随后,在数据流中重复调用 read()函数,直到这个块全部读完为止。如果第一个block块的数据读完,就会关闭指向第一个block块的datanode 连接,接着读取下一个block块
6.如果第一批block都读完了,DFSInputStream就会去NameNode拿下一批blocks的location,然后继续读,如果所有的block块都读完,这时就会关闭掉所有的流。
注意:read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode只是返回Client请求包含块的DataNode 地址,并不是返回请求块的数据。 最终读取所有的block会合并成一个完整的最终文件。

猜你喜欢

转载自blog.csdn.net/sun_0128/article/details/107127323