hadoop入门(12):hdfs的读写流程
作者:互联网
hdfs的写入流程
文件具体上传流程如下:
-
创建文件:
- 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计算校验和chunksum值(4字节)
- 然后将chunk和对应的校验写入packet中,一个packet是64kb
- 随着源源不断的带校验chunk写入packet,当packet写满之后将其写入dataqueue队列中
- packet从队列中取出,沿着pipeline发送到dn1,再从dn1发送到dn2,dn2发送到dn3
- 同时,这个packet也会保存一份到一个确认队列ack queue中
- packet到达最后一个datanode即nd3之后会做检验,然后将检验沿结果逆着pipeline方向传回客户端,具体检验结果从dn3传到dn2,dn2做检验,dn2传到dn1,dn1做检验,结果再传回客户端。
- 客户端根据校验结果,如果“成功”,则将保存在ack queue中的packet删除,如果失败则将packet取出重新放回到dataqueue末尾,等待沿pipeline再次传输。
- 如此将block中一个数据的一个个packet发送出去。当block发送完毕,即dn1,dn2,dn3都接收了blk1的副本,那么三个datanode分别RPC调用namenode的blockReceivedAndDeleted(),namenode会更新内存中block与datanode的对应关系(比如dn1上多了个blk1)
-
关闭三个datanode构建的pipeline,且文件还有下一个块的时候,再从4开始直到全部文件写完
- 最终,调用DFSOutputStream的close()。
- 客户端调用namenode的complete(),告知namenode文件传输完成。
HDFS写数据-容错
Q: 如果在传输过程中dn2挂了,则当前piprline中断,hdfs会怎么样?
A: 客户端RPC会调用namenode的updateBlockPipeline()为当前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发现其上面的blk1的时间戳是老的,会让datanode将blk1删除掉。
hdfs的读取流程
文件的具体读取流程如下:
- Client端读取hdfs文件,client调用文件系统对象DistributedFileSystem的open方法
- 返回FSDataInputStream对象(对DFSInputStream的包装)
- 构造DFSInputStream对象时,调用namenode的getBlockLocation方法,获得file开始的若干个block的存储datanode列表;针对每个block的dn列表,会根据网络拓扑排序,离client近的排在前面。
- 调用DFSInputStream的read方法读取blk1的数据,与client最近的datanode建立连接,读取数据。
- 读取完后,关闭与dn建立的流。
- 重复4、5、6步骤,紧接着读取下一个块的数据,直到这一批块的数据读完。
- 读取下一批块,重复3、4、5、6、7
- 调用FSDataInputStream的close方法
HDFS读数据-容错
Q: 读取block数据时,client与datanode连接中断会怎么办?
A: client与第二个存储此block的datanode建立连接,存储数据。记录出问题的datanode,不会再从其上读取数据。
Q: client读取数据时,发现block块的数据有问题怎么办?
A: client读取数据时,同时会读取到block的校验和,若client针对读取的block计算校验和发现与其读取的校验和不一致,说明block损坏。client会从其它存放此block的datanode读取数据,同样会计算校验和,同时告诉namenode此情况。
标签:hdfs,12,blk1,hadoop,packet,client,datanode,namenode,block 来源: https://www.cnblogs.com/S2Jgogo/p/15978061.html