赞
踩
文件上传流程如下:
创建文件:
①HDFS client向HDFS写入数据,先调用DistributedFileSystem.create()
②RPC调用namenode的create(),会在HDFS目录树中指定的路径,添加新文件;并将操作记录在edits.log中
namenode.create()方法执行完后,返回一个FSDataOutputStream,它是DFSOutputStream的包装类
建立数据流管道pipeline
③client调用DFSOutputStream.write()写数据(先写第一个块的数据,暂时叫blk1)
④DFSOutputStream通过RPC调用namenode的addBlock,向namenode申请一个空的数据块block
⑤addBlock返回LocatedBlock对象;此对象中包含了当前blk要存储在哪三个datanode的信息,比如dn1、dn2、dn3
⑥客户端,根据位置信息,建立数据流管道(图中蓝色线条)
向数据流管道写当前块的数据
⑦写数据时,先将数据写入一个检验块chunk中,写满512字节后,对此chunk计算校验和checksum值(4字节)
⑧然后将chunk及对应校验和写入packet中,一个packet是64KB
⑨随着源源不断的带校验和的chunk写入packet,当packet写满后,将packet写入dataqueue数据队列中
⑩packet从队列中取出,沿pipeline发送到dn1,再从dn1发送到dn2,再从dn2发送到dn3
⑪同时,此packet会保存一份到一个确认队列ack queue中
⑫packet到达最后一个datanode即dn3后,做校验,将校验结果逆着pipeline方向回传到客户端,具体是校验结果从dn3传到dn2,dn2也会做校验,校验结果再
传到dn1,dn1也做校验;结果再传回客户端
⑬客户端根据校验结果,如果“成功”,则将将保存在ack queue中的packet删除;如果失败,则将packet取出,重新放回到data queue末尾,等待再次沿pipeline发送
⑭如此,将block中的一个数据一个个packet发送出去;当此block发送完毕,
即dn1、dn2、dn3都接受了blk1的完整的副本,那么三个dn分别RPC调用namenode的blockReceivedAndDeleted(),
namenode会更新内存中block与datanode的对应关系(比如dn1上多了一个blk1副本)
关闭dn1、dn2、dn3构建的pipeline;且文件还有下一个块时,再从④开始;直到文件全部数据写完
⑮最终,调用DFSOutputStream的close()
⑯客户端调用namenode的complete(),告知namenode文件传输完成
容错
假设说当前构建的pipeline是dn1、dn2、dn3构成的
当传输数据的过程中,dn2挂了或通信不畅了,则当前pipeline中断
HDFS会如何做?
先将ack queue中的所有packet全部放回到data queue中
客户端RPC调用namenode的updateBlockForPipeline(),为当前block(假设是blk1)生成新的版本比如ts1(本质是时间戳)
故障dn2会从pipeline中删除
DFSOutputStream再RPC调用namenode的getAdditionalDatanode(),让namenode分配新的datanode,比如是dn4
输出流将原dn1、dn3与新的dn4组成新的管道,他们上边的blk1版本设置为新版本ts1
由于新添加的dn4上没有blk1的数据,客户端告知dn1或dn3,将其上的blk1的数据拷贝到dn4上
新的数据管道建立好后,DFSOutputStream调用updatePipeline()更新namenode元数据
至此,pipeline恢复,客户端按正常的写入流程,完成文件的上传
故障datanode重启后,namenode发现它上边的block的blk1的时间戳是老的,会让datanode将blk1删除掉
6.2.2 容错
情况一:读取block过程中,client与datanode通信中断
情况二:client读取block,发现block数据有问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。