8.HDFS读文件刨析(从HDFS文件上下载到本地)

从本地下载HDFS文件

1)客户端向namenode请求下载文件,namenode通过查询元数据,找到文件块所在的datanode地址。

2)挑选一台datanode(就近原则,然后随机)服务器,请求读取数据。

3datanode开始传输数据给客户端(从磁盘里面读取数据放入流,以packet为单位来做校验)。

4)客户端以packet为单位接收,先在本地缓存,然后写入目标文件。

  1. 首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例。
  2. DistributedFileSystem通过rpc获得文件的第一批blocklocations同一个block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面。
  3. 前两步会返回一个FSDataInputStream对象,该对象会被封装DFSInputStream对象,DFSInputStream 以方便的管理datanodenamenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode 并连接。
  4. 数据从datanode源源不断的流向客户端。
  5. 如果第一块的数据读完了,就会关闭指向第一块的datanode连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。
  6. 如果第一批block都读完了, DFSInputStream就会去namenode拿下一批blocklocations,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。
  7. 如果在读数据的时候, DFSInputStreamdatanode的通讯发生异常,就会尝试正在读的block的排序第二近的datanode,并且会记录哪个 datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后 DFSInputStream在其他的datanode上读该block的镜像。
  8. 该设计就是客户端直接连接datanode来检索数据并且namenode来负责为每一个block提供最优的datanode namenode仅仅处理block location的请求,这些信息都加载在namenode的内存中,hdfs通过datanode集群可以承受大量客户端的并发访问。

@Test
    public void getFileHdfs1() throws URISyntaxException, IOException, InterruptedException {

    Configuration conf = new Configuration();

    FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"),conf,"root");

    FSDataInputStream fis = fs.open(new Path("/123"));

    FileOutputStream fos = new FileOutputStream(new File("D:\\input\\test\\aa.txt"));

    IOUtils.copyBytes(fis,fos,1024*5,true);


    System.out.println("下载成功");

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SuperBigData~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值