当前位置:   article > 正文

HDFS读写流程及容错_hdfs的读取、写入,容错处理

hdfs的读取、写入,容错处理
1. 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计算校验和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删除掉

2. hdfs的读取流程及容错

在这里插入图片描述

  • 1、client端读取HDFS文件,client调用文件系统对象DistributedFileSystem的open方法
  • 2、返回FSDataInputStream对象(对DFSInputStream的包装)
  • 3、构造DFSInputStream对象时,调用namenode的getBlockLocations方法,获得file的开始若干block(如blk1, blk2, blk3, blk4)的存储datanode(以下简称dn)列表;针对每个block的dn列表,会根据网络拓扑做排序,离client近的排在前;
  • 4、调用DFSInputStream的read方法,先读取blk1的数据,与client最近的datanode建立连接,读取数据
  • 5、读取完后,关闭与dn建立的流
  • 6、读取下一个block,如blk2的数据(重复步骤4、5、6)
  • 7、这一批block读取完后,再读取下一批block的数据(重复3、4、5、6、7)
  • 8、完成文件数据读取后,调用FSDataInputStream的close方法

6.2.2 容错

  • 情况一:读取block过程中,client与datanode通信中断

    • client与存储此block的第二个datandoe建立连接,读取数据
    • 记录此有问题的datanode,不会再从它上读取数据
  • 情况二:client读取block,发现block数据有问题

    • client读取block数据时,同时会读取到block的校验和,若client针对读取过来的block数据,计算检验和,其值与读取过来的校验和不一样,说明block数据损坏
    • client从存储此block副本的其它datanode上读取block数据(也会计算校验和)
    • 同时,client会告知namenode此情况;
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号