java hdfs 批量写数据_客户端读写hdfs数据

本文详细介绍了HDFS的读写过程。在读取时,客户端通过FileSystem对象打开文件,Namenode返回文件块的位置,然后客户端通过FSDataInputStream从Datanodes读取数据。在写入时,客户端创建文件,DataStreamer处理数据队列,建立与Datanodes的管道,确保数据的冗余备份。Namenode监控块的复制,确保数据安全性。整个过程对客户端透明。
摘要由CSDN通过智能技术生成

读:

03253acafc1190656d26fc047abd0340.png

(1)客户端通过调用FIleSystem对象的open()方法来打开希望读取的文件,对于hdfs来说,这个对象是分布式文件系统的一个实例。

(2)DistributedFileSystem通过使用rpc来调用namenode,以确定文件起始块的位置。对于每一个块,namenode返回存有该块副本的datanode的地址。此外,这些datanode根据他们与客户端的距离来排序(机架感应)。如果该客户端本身就是一个datanode(比如,在一个MapReduce任务中),并保存有相应数据块的一个副本时,该节点将从本地datanode中读取数据。

(3)DistributedFileSystem类返回一个FSDataInputStream对象(支持文件定位的输入流)给客户端读取数据。FSDataInput类转而封装DFSInputStream对象,该对象管理着datanode、namenode的I/O。接着,客户端对这个输入流调用read()方法。

(4)存储着文件起始块的datanode地址的DFSInputStream 随即连接距离最近的文件中第一个块所在的datanode。通过对数据流反复调用read()方法,可以将数据从datanode传输到客户端。

(5)到达块的末端时,DFSInputStream 会关闭与该datanode的连接,然后寻找下一个块的最佳datanode。客户端只需要读取连续的流,并且对于客户端都是透明的。客户端从流中读取数据时,块是按照打开DFSInputStream与datanode新建连接的顺序读取的。它根据需要询问namenode来检索下一批所需块的datanode的位置。

(6)一旦客户端读取完成,就对FSDataInputStream调用close()方法,在读取数据的时候,如果DFSInputStream在与datanode通信时遇到错误,它便尝试从这个块的另外一个最邻近的datanode读取数据。它也会记住哪个故障的datanode,以保证以后不会反复读取该节点上后续的块。DFSInputStream也会通过校验和确认从datanode发来的数据是否完整。如果发现一个损坏的块,它就会在DFSInputStream 试图从其他datanode读取一个块的副本,也会将被损坏的块通知给namonode。

这个设计的一个重点是,客户端可以直接连接到datanode检索数据,且namenode告诉客户端每个块中的最佳datanode。由于数据流分散在该集群中所有的datanode,所以这种设计能使HDFS可扩展到大量的并发客户端。同时,namenode仅需要响应快位置的请求(这些信息存储在内存中,因而非常高效),而无需响应数据请求,否则随着客户端数量的增长,namenode很快会成为一个瓶颈。

hadoop写:

f7cee27159b15f7e847019c0822b8791.png

(1)客户端通过对DistributeFileSystem 对象调用create()函数来创建文件。

(2)DistributedFileSystem 对namenode创建一个rpc调用,在文件系统的命名空间中创建一个新文件,但是此时该文件中还没有相应的数据块,namenode执行各个不同的检查以确保这个文件不存在,并且客户端有创建该文件的权限。如果这些检查均通过,namenode就会为创建新文件记录一条记录,否则,文件创建失败并向客户端抛出一个IoException异常。

(3)DistributeFileSystem向客户端返回一个FSDataOutrputStream对象,由此客户端可以开始写入数据。就像读取事件一样,FSDataOutputStream封装一个DFSoutputstream对象,该对象负责处理datanode和namenode之间的通信。在客户端写入数据时,DFSoutputStream将它分成一个个的数据包,并写入内部队列,成为数据队列(data queue)

(4)dataStreamer处理数据队列,它的责任是根据datanode列表来要求namenode分配适合的新块来存储数据备份。这一组datanode构成一个管道(pip管道)---我们假设副本数是3,所以管道中有3个节点。dataStream将数据包流式传输到管道中第一个datanode,该datanode存储数据包之后,并将它发送到管道中第二个datanode中,同样操作,第二个datanode 将数据包存储后给第三个datanode。

(5)DFSOoutputStream也维护着一个内部数据包队列来等待datanode的收到确认回执,称为"确认队列"(ack queue)。当收到管道中所有的datanode确认信息后,该数据包才会从确认队列删除。

如果在数据写入期间,datanode发生故障,则执行以下操作,这对与写入数据的客户端是透明的。首先关闭管道,确认把队列中的任何数据包都添回数据队列的最前端,以确保故障节点下游的datanode不会漏掉任何一个数据包。为存储在另一个正常datanode的当前数据块制定一个新的标识,并将该标识传送给namenode。以便故障datanode在恢复后可以删除存储的部分数据块。从管道中删除故障数据节点并且把余下的数据块写入管道中剩余的两个正常的datanode。namenode注意到块副本量不足时,会在另一个节点上创建一个新的副本。后续的数据块继续正常接受处理。

(6)客户端完成数据的写入后,会对数据流调用close()方法。

(7)该操作将剩余的所有数据包写入datanode管道中,并在联系namenode发送文件写入完成信号之前,等待确认。namenode已经知道文件由哪些块组成(通过DataStreamer询问数据块的分配),所以它在返回成功只需要等待数据块进行最小量的复制。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值