HDFS的读写流程

1. 读流程的详解

读操作:

        - hdfs dfs -get /file02 ./file02
        - hdfs dfs -copyToLocal /file02 ./file02
        - FSDataInputStream fsis = fs.open("/input/a.txt");
        - fsis.read(byte[] a)
        - fs.copyToLocal(path1,path2)
官网图如下:

 详细图解

1. 客户端通过调⽤FileSystem对象的open()⽅法来打开希望读取的⽂件,对于 HDFS来说,这个对象是DistributedFileSystem,它通过使⽤远程过程调⽤(RPC) 来调⽤namenode,以确定⽂件起始块的位置

2. 对于每⼀个块 ,NameNode 返回存有该块副本的 DataNode 地址 , 并根据距离客户端 的远近来排序。
3. DistributedFileSystem 实例会返回⼀个 FSDataInputStream 对象(⽀持⽂ 件定位功能)给客户端以便读取数据,接着客户端对这个输⼊流调⽤read() ⽅法
4. FSDataInputStream 随即连接距离最近的⽂件中第⼀个块所在的 DataNode, 通过 对数据流反复调⽤read() ⽅法,可以将数据从 DataNode 传输到客户端
5. 当读取到块的末端时, FSInputStream 关闭与该 DataNode 的连接,然后寻找下⼀ 个块的最佳DataNode
6. 客户端从流中读取数据时,块是按照打开 FSInputStream DataNode 的新建连接 的顺序读取的。它也会根据需要询问NameNode 来检索下⼀批数据块的 DataNode 的位 置。⼀旦客户端完成读取,就对FSInputStream 调⽤ close ⽅法
注意:在读取数据的时候,如果 FSInputStream DataNode 通信时遇到错误,会尝 试从这个块的最近的DataNode 读取数据,并且记住那个故障的 DataNode, 保证后续不 会反复读取该节点上后续的块。FInputStream 也会通过校验和确认从 DataNode 发来 的数据是否完整。如果发现有损坏的块,FSInputStream 会从其他的块读取副本,并将损坏的块通知给NameNode

2. 写流程的详解

写操作:
        - hdfs dfs -put ./file02 /file02
        - hdfs dfs -copyFromLocal ./file02 /file02
        - FSDataOutputStream fsout = fs.create(path);
fsout.write(byte[])
        - fs.copyFromLocal(path1,path2)

官网图如下:

 详细图解

         图中的1和2. 客户端(操作者)通过调⽤DistributedFileSystem对象的create()⽅ 法(内部会调⽤HDFSClient对象的 create()⽅法),实现在namenode上创建新的⽂件并返回⼀个FSDataOutputStream 对象

1)DistributedFileSystem 要通过 RPC 调⽤ namenode 去创建⼀个没有 blocks 关联的 新⽂件,此时该⽂件中还没有相应的 数据块信息
2) 但是在新⽂件创建之前 ,namenode 执⾏各种不同的检查,以确保这个⽂件不存在以及 客户端有新建该⽂件的权限。如果 检查通过, namenode 就会为创建新⽂件记录⼀条 事务记录( 否则,⽂件创建失败并向客户端抛出⼀个 IOException 异常 ) 。 DistributedFileSystem向客户端返回⼀个 FSDataOuputStream 对象
3.FSDataOutputStream 被封装成 DFSOutputStream DFSOutputStream 能够协调 namenode和 datanode 。客户端开始 写数据到 DFSOutputStream , DFSOutputStream会把数据分成⼀个个的数据包 (packet) ,并写⼊⼀个内部队列,这 个队列称为“ 数据队列 data queue
4.DataStreamer 会去处理接受 data quene ,它先询问 namenode 这个新的 block 最适合存储的在哪⼏个datanode ⾥(⽐⽅副本数是 3 。那么就找到 3 个最适合的 datanode),把他们排成⼀个 pipeline DataStreamer packet 按队列输出到管道的第⼀个datanode 中。第⼀个 datanode ⼜把 packet 输出到第⼆个 datanode 中。以此类推。DataStreamer 在将⼀个 packet 流式的传到第⼀个 DataNode 节点后, 还会将 packet 从数据队列移动到另⼀个队列确认队列 (ack queue) . 确认队列也是由packet 组成,作⽤是等待 datanode 完全接收完数据后接收响应 .
5.datanode 写⼊数据成功之后,会为 ResponseProcessor 线程发送⼀个写⼊成功的 信息回执,当收到管道中所有的datanode 确认信息后, ResponseProcessoer 线程会 将该数据包从确认队列中删除。
6. 客户端写完数据后会调⽤ close() ⽅法 , 关闭写⼊流 .
7.DataStreamer 把剩余的包都刷到 pipeline ⾥,然后等待 ack 信息,收到最后⼀个 ack后,客户端通过调⽤ DistributedFileSystem 对象的 complete() ⽅法来告知 namenode数据传输完成 .
注意点 1 如果任何 datanode 在写⼊数据期间发⽣故障,则执⾏以下操作:
1. ⾸先关闭管道,把确认队列中的所有数据包都添加回数据队列的最前端,以确保故障 节点下游的datanode 不会漏掉任何⼀个数据包
2. 为存储在另⼀正常 datanode 的当前数据块制定⼀个新标识,并将该标识传送给namenode,以便故障 datanode 在恢复后可以删除存储的部分数据块
3. 从管道中删除故障 datanode ,基于两个正常 datanode 构建⼀条新管道,余下数据 块写⼊管道中正常的datanode
4. namenode 注意到块复本不⾜时,会在⼀个新的 Datanode 节点上创建⼀个新的复 本。
注意点 2
        注意:在⼀个块被写⼊期间可能会有多个datanode 同时发⽣故障,但概率⾮常低。只要 写⼊了dfs.namenode.replication.min 的复本数(默认 1 ),写操作就会成功,并 且这个块可以在集群中异步复制,直到达到其⽬标复本数dfs.replication 的数量(默 认3

注意点3

        client运⾏write操作后,写完的block才是可⻅的,正在写的blockclient是不 可⻅的,仅仅有调⽤sync⽅法。client才确保该⽂件的写操作已经全部完毕。当 client调⽤close⽅法时,会默认调⽤sync⽅法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值