hadoop2.x-hdfs读流程

hdfs client: DistributedFileSystem.open() ->ClientProtocol.open()
           -> DFSInputStream
               Namenode :DataNode address
                        ClientProtocol.getBlockLocations() 获取数据块起始位置信息
                        按照与客户端距离远近排序
                        选择最优Datanode节点
               最优Datanode节点: 读取数据块

               DFSInputStream.read()
                读取 packet
                到达数据块末尾

               再次调用ClientProtocol.getBlockLocations()获取文件下一个数据块位置信息
               并建立新的数据块最优节点之间连接
               然后继续

               如果出现数据块异常 切换另一个保存副本的数据节点
                    数据packet包含校验值 数据 
                    ->ClientProtocol.reportBadBlocks()向NameNode汇报损坏的数据块副本
                    DFSInputStream 尝试从其他数据节点读取数据块

               以此类推....

               读取完所有数据块
            HDFSDataInputStream.close()方法关闭输入流

1.首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例
2.DistributedFileSystem通过rpc获得文件的第一批个block的locations,同一block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面.
3.前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode并连接(参考第一小节)。
4.数据从datanode源源不断的流向客户端。
5.如果第一块的数据读完了,就会关闭指向第一块的datanode连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。
6.如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。

如果在读数据的时候,DFSInputStream和datanode的通讯发生异常,就会尝试正在读的block的排第二近的datanode,并且会记录哪个datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode。DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后DFSInputStream在其他的datanode上读该block的镜像

该设计的方向就是客户端直接连接datanode来检索数据并且namenode来负责为每一个block提供最优的datanode,namenode仅仅处理block location的请求,这些信息都加载在namenode的内存中,hdfs通过datanode集群可以承受大量客户端的并发访问。

==================================

1.首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例
2.DistributedFileSystem通过rpc获得文件的第一批个block的locations,同一block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面.
3.前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode并连接(参考第一小节)。
4.数据从datanode源源不断的流向客户端。
5.如果第一块的数据读完了,就会关闭指向第一块的datanode连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。
6.如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。

如果在读数据的时候,DFSInputStream和datanode的通讯发生异常,就会尝试正在读的block的排第二近的datanode,并且会记录哪个datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode。DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后DFSInputStream在其他的datanode上读该block的镜像

该设计的方向就是客户端直接连接datanode来检索数据并且namenode来负责为每一个block提供最优的datanode,namenode仅仅处理block location的请求,这些信息都加载在namenode的内存中,hdfs通过datanode集群可以承受大量客户端的并发访问。

==========================
客户端程序将数据通过这个流写入到内部缓存。
数据被分割成packet,每个包64k

一个packet由chunk组成。每个chunk是512字节,相应的关联一个校验和

当客户端程序填满当前的packet,会填充到dataQueue(数据队列)。
DataStreamer 线程从dataQueue(数据队列)抓取数据,并将其通过管线发送到第一个datanode
接着将数据从dataQueue(数据队列)移动到ackQueue(确认队列)。当收到所有数据节点的确认回执
ResponseProcessor(响应处理器)会将数据从ackQueue(确认队列)中移除

如果出现错误,所有未完成的包将从ackQueue(确认队列)移出
通过清除错误数据节点的管线,生成一个新的管线
DataStreamer开始重新传输数据

======================

  1. client和namenode进行通信查询元数据(block所在的datanode节点),找到block所在的datanode服务器

  2. 挑选一台datanode,请求建立连接(就近原则,然后随机),请求建立socket流

  3. datanode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验)

  4. 客户达以packet为单位接受,首先在本地缓冲,然后写入目标文件,后面的block追加合并到这个文件,最后合成最终需要的文件

===================================

Client调用FileSystem.open()方法:
  1 FileSystem通过RPC与NN通信,NN返回该文件的部分或全部block列表(含有block拷贝的DN地址)。

2 选取举栗客户端最近的DN建立连接,读取block,返回FSDataInputStream。

Client调用输入流的read()方法:
  1 当读到block结尾时,FSDataInputStream关闭与当前DN的连接,并未读取下一个block寻找最近DN。

2 读取完一个block都会进行checksum验证,如果读取DN时出现错误,客户端会通知NN,然后再从下一个拥有该block拷贝的DN继续读。

3 如果block列表读完后,文件还未结束,FileSystem会继续从NN获取下一批block列表。

关闭FSDataInputStream

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值