HDFS的读写流程
读取过程分析
1、客户端或用户通过调用FileSystem对象的open()方法打开需要读取的文件,这是常见的读取实例。
2、FileSystem通过远程协议调用NameNode确定文件的前几个Block的位置。对于每一个Block,NameNode返回一含有那个Block拷贝的“元数据”,及文件基本信息;接下来,DataNode按照定义的距离值进行排序,如果Client本身就是一个DataNode,那么优先从本地DataNode节点读取数据。HDFS实例做完以上工作后,返回一个FSDataInputStream给客户端,让其从FSDataInputStream中读取数据。FSDataInputStream接着包装一个DFSInputStream,用来管理DataNode和NameNode的I/O。
3、NameNode向客户端返回一个包含数据信息的地址,客户端根据地址创建一个FSDataInputStream开始对数据进行读取。
4.FSDataInpuStream根据开始是存放的前几个Blocks的DataNode的地址,连接到最近的DataNode上对数据从头读取。客户端反复调用read()方法,以流式方式从DataNode读取数据。
5、当读取Block结尾的时候,FSDataInputStream会关闭当前DataNode的链接,然后查找能够读取下一个Block的最好的DataNode。这些操作对客户端是透明的,客户端感觉到的是连续的流,也就是说读取的时候就开始查找下一个块所在的地址。
6、读取完成调用close()方法,关闭FSDataInputStream
写入过程分析
1、Client通过调用FileSystem的create()方法来请求创建文件
2、FileSystem通过对NameNode发出远程请求,在NameNode里面创建一个新的文件,但此时并不关联任何的块。NameNode进行很多检查来保证不存在要创建的文件已经存在于文件系统中,同时检查是否有相应的权限来创建文件。如果这些检查都完成了,那么NameNode将记录下来这个新文件的信息.FileSystem返回一个FSDataOutputStream给客户端来写入数据。和读的情形一样,FSDataOutputStream将包装一个DFSOutputStream用于和DataNode及NameNode通信。而且一但文件创建失败,客户端会收到一个IOExpection,表示文件创建失败,停止后续操作。
3、客户端开始写数据。FSDataOutputStream把要写入的数据分成包的形式,将其写入到中间队列中。其中的数据由DataStreamer来读取。DataStreamer的职责是让NameNode来分配新的块——通过找出合适的DataNode——来存储作为备份而复制的数据。这些DataNode组成一个流水线,我们假设这个流水线是个三级流水线,那么里面将含有三个节点。此时, DataStreamer 将数据首先写入到流水线中的第一个节点。此后由第一个节点将数据包传送并写入到第二个节点,然后第二个将数据包传送并写入到第三个节点。
4、FSDataOutputStream维护了一个内部关于packets的队列,里面存放等着被DataNode确认无误的packets的信息。这行队列称为等待队列。一个 packet 的信息被移出本队列当且仅当 packet 被流水线中的所有节点都确认无误。
5、当完成数据写入之后客户端调用流的 close 方法,在通知 NameNode 完成写入之前,这个方法将 flush 残留的 packets,并等待确认信息( acknowledgement)。 NameNode 已经知道文件由哪些块组成(通过 DataStream 询问数据块的分配),所以它在返回成功前只需要等待数据块进行最小值复制。