深入剖析HDFS读写流程

 一、读取数据流程

1、原理图

2、流程剖析

a)客户端首先调用DistributedFileSystem对象的open方法,去和namenode建立rpc通信,请求namenode返回文件的元信息。

b)namenode得到请求,会在内存中寻找文件元信息,内存中找不到则再去fsimage文件中找。找到后给客户端返回部分(读取文件较大)或全部的block列表,即FSDataInputStream对象。

c)客户端调用FSDataInputStream对象的read()方法,从离客户端最近的block副本进行block块的读取,直到这个block块的所有信息读取完毕,然后再进行该block的校验,校验成功则读取下一个block块数据,校验失败则通知namenode并从另一个副本读取数据。

d)如果block列表中数据读取完毕,文件读取还没有结束,DistributedFileSystem对象会从namenode那儿获取下一批的block列表,再次进行block数据的读取。

e)文件读取完毕,客户端会将所有block块拼成一个完整的最终文件,然后调用FSDataInputStream对象的close()方法,关闭输入流,读取结束。

注意:

1、namenode返回的block列表中的block是经过了排序的,离客户端近的排在前面,心跳机制中超时汇报的排在后面。

2、读取实际上是多线程方式并行读取,流程中所说的一个一个block块读取实际上是从单线程的角度考虑的,这样方便描述。

 二、写入数据流程

1、原理图

 2、流程剖析

a)客户端首先调用DistributedFileSystem对象的create方法,去和namenode建立rpc通信,请求写入数据。

b)namenode收到请求,会进行诸如文件是否存在、用户是否拥有相应权限等一系列的检查。若检查通过,  则为该次上传建立一次记录,并返回给客户端一个FSDataOutputStream对象;检查不通过,返回给客户端异常信息。

c)客户端拿到FSDataOutputStream对象后先对文件进行线性切块,然后会调用FSDataOutputStream对象的write()方法,开始上传第一个block块,上传前会在block的三个副本对应的机器之间建立一条pipeline通道。每次成功写入一个packet到第一台机器上,三台机器立马通过pipeline进行数据的同步,每次第一台机子通过pipeline成功向后传一个packet,就会放入一个ack packet到应答队列等待应答。

d)每一个block的最后一个packet上传完毕后,datanode给应答队列返回应答信息,然后client会请求namenode上传下一个block数据,直到所有block上传完毕。

e)上传完毕后,客户端调用FSDataOutputStream对象的close()和flush()关闭刷新输出流,然后通知namenode上传完毕。



注意:
    数据的写入以packet为单位,每个packet大小为64KB,这些packet存在数据队列中。

上传时的datanode宕机问题:
    1、pipeline关闭,所有确认队列相关数据包发送到数据队列头部重新上传。
    2、宕机节点移除,其他数据节点形成新的管线,继续block未完数据的上传,完成结束后namenode会自动安排一个新的副本以达到冗余度要求。
    3、多个节点宕机,只要上传后副本数满足属性hdfs-site.xml文件中dfs.relication.min属性确认的最少副本数要求,就算上传成功。
    

猜你喜欢

转载自blog.csdn.net/pengzonglu7292/article/details/89208055