hadoop2.x-hdfs写流程

写流程

1.客户端通过调用DistributedFileSystem的create方法创建新文件

2.DistributedFileSystem通过RPC调用namenode去创建一个没有blocks关联的新文件,创建前,namenode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,namenode就会记录下新文件,否则就会抛出IO异常.

3.前两步结束后会返回FSDataOutputStream的对象,象读文件的时候相似,FSDataOutputStream被封装成DFSOutputStream.DFSOutputStream可以协调namenode和datanode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列data quene。

4.DataStreamer会去处理接受data quene,他先问询namenode这个新的block最适合存储的在哪几个datanode里(参考第二小节),比如重复数是3,那么就找到3个最适合的datanode,把他们排成一个pipeline.DataStreamer把packet按队列输出到管道的第一个datanode中,第一个datanode又把packet输出到第二个datanode中,以此类推。

5.DFSOutputStream还有一个对列叫ack quene,也是有packet组成,等待datanode的收到响应,当pipeline中的所有datanode都表示已经收到的时候,这时akc quene才会把对应的packet包移除掉。
如果在写的过程中某个datanode发生错误,会采取以下几步:
1) pipeline被关闭掉;
2)为了防止防止丢包ack quene里的packet会同步到data quene里;
3)把产生错误的datanode上当前在写但未完成的block删掉;
4)block剩下的部分被写到剩下的两个正常的datanode中;
5)namenode找到另外的datanode去创建这个块的复制。当然,这些操作对客户端来说是无感知的。

6.客户端完成写数据后调用close方法关闭写入流

7.DataStreamer把剩余得包都刷到pipeline里然后等待ack信息,收到最后一个ack后,通知datanode把文件标示为已完成。

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

1.客户端通过调用DistributedFileSystem的create方法创建新文件

2.DistributedFileSystem通过RPC调用namenode去创建一个没有blocks关联的新文件,创建前,namenode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,namenode就会记录下新文件,否则就会抛出IO异常.

扫描二维码关注公众号,回复: 1652052 查看本文章

3.前两步结束后会返回FSDataOutputStream的对象,象读文件的时候相似,FSDataOutputStream被封装成DFSOutputStream.DFSOutputStream可以协调namenode和datanode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列data quene。
4.DataStreamer会去处理接受data quene,他先问询namenode这个新的block最适合存储的在哪几个datanode里(参考第二小节),比如重复数是3,那么就找到3个最适合的datanode,把他们排成一个pipeline.DataStreamer把packet按队列输出到管道的第一个datanode中,第一个datanode又把packet输出到第二个datanode中,以此类推。
5.DFSOutputStream还有一个对列叫ack quene,也是有packet组成,等待datanode的收到响应,当pipeline中的所有datanode都表示已经收到的时候,这时akc quene才会把对应的packet包移除掉。
如果在写的过程中某个datanode发生错误,会采取以下几步:1) pipeline被关闭掉;2)为了防止防止丢包ack quene里的packet会同步到data quene里;3)把产生错误的datanode上当前在写但未完成的block删掉;4)block剩下的部分被写到剩下的两个正常的datanode中;5)namenode找到另外的datanode去创建这个块的复制。当然,这些操作对客户端来说是无感知的。
6.客户端完成写数据后调用close方法关闭写入流
7.DataStreamer把剩余得包都刷到pipeline里然后等待ack信息,收到最后一个ack后,通知datanode把文件标示为已完成。

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

1、通过配置文件获取DistributedFileSystem实例
2、初始化校验和类型和大小 ===> 类型CRC32C,大小4byte //对每个chunk进行校验,chunk大小512字节
3、创建namenode元数据:
在DFSOutputStream中dfsClient.namenode.create
4、使用computePacketChunkSize方法对packet和chunk进行计算 //计算每个packet中的chunk数量(126)
5、使用DFSPacket初始化包对象
6、writeChecksumChunks写入数据:方法,最终使用System.arrayCopy方法:
先写入4 x 9字节的checksum
再写入512 x 9字节的chunk

7、waitAndQueueCurrentPacket:将数据放入dataQueue中。接着notifyAll,唤醒DataStreamer线程

8、DataStreamer:设置管线,然后打开datanode的传输流,
底层传输使用的是nio的非阻塞技术
protobuf串行化技术

9、数据写入成功的时候:
dataQueue.removeFirst(); //将数据队列中的第一个数据删除
ackQueue.addLast(one); //将此数据移动到确认队列的末尾
dataQueue.notifyAll(); //通知DataStreamer继续传输包

10、将数据实例化到磁盘的过程:
先把checksum和data之间的鸿沟去掉:
移动checksum数据到data数据之前
移动header数据到checksum之前

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

客户端通过hadoop文件系统相关api发送请求打开一个要写入的文件,若该用户有足够的权限,请求送抵NameNode,在NameNode上建立该文件的元数据

客户端收到“打开文件成功”的响应

客户端将数据写入流,数据会自动拆分成数据包,并将数据包保存在内存队列中

客户端的独立线程从队列中读取数据包,同时向NameNode请求一组DataNode列表,以便写入数据块的多个副本

客户端直接连接列表中的第一个DataNode,该DataNode又连接到第二个DataNode,第二个又连接第三个,建立数据块的复制管道

数据包以流的方式写入第一个DataNode的磁盘,同时传入管道中的下一个DataNode并写入其磁盘,以此类推

复制管道中的每个DataNode都会确认所收到数据包已成功写入磁盘

客户端维护一张列表,记录哪些数据包尚未收到确认消息,每收到一个响应,客户端便知道数据已成功写入到管道中的一个DataNode

当数据块被写满时,客户端将重新向NameNode申请下一组DataNode

客户端将剩余数据包全部写入磁盘,关闭数据流并通知NameNode文件写操作已完成

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

1. 客户端向namenode请求上传文件, namenode检查目标文件是否存在,夫目录是否存在

2. namenode 返回可使用资源 ,客户端根据使用资源对要写入的数据进行分块

3. 客户端请求第一个block上传位置

4. namenode返回3个datanode节点,分别为data1 ,data2 ,data3

5. 客户端请求向第一个data1上传block,data1收到请求后会调用data2,然后data2调用data3,将通道建立完成,逐级应答客户端

6. 客户端开始向data1上传第一个block(先从磁盘读取数据放到一个本地内存缓冲),单位为packet(一个packet为64kb),在写入data1的时候会进行数据校验,它并不是通过一个packet进行一次校验而是以chunk为单位进行校验(512byte),data1收到packet就会传给data2,data2传给data3,第一台每传一个packet会放入一个应答队列等待应答

7. 当一个block传输完成之后,datanode进行报告给namenode存储的块信息,同时也告诉客户端写入成功

8. 客户端再次请求namenode上传第二个block的服务器(重复执行3-7步)

==============================
1、通过配置文件获取DistributedFileSystem实例
2、初始化校验和类型和大小 ===> 类型CRC32C,大小4byte //对每个chunk进行校验,chunk大小512字节
3、创建namenode元数据:
在DFSOutputStream中dfsClient.namenode.create
4、使用computePacketChunkSize方法对packet和chunk进行计算 //计算每个packet中的chunk数量(126)
5、使用DFSPacket初始化包对象
6、writeChecksumChunks写入数据:方法,最终使用System.arrayCopy方法:
先写入4 x 9字节的checksum
再写入512 x 9字节的chunk

7、waitAndQueueCurrentPacket:将数据放入dataQueue中。接着notifyAll,唤醒DataStreamer线程

8、DataStreamer:设置管线,然后打开datanode的传输流,
底层传输使用的是nio的非阻塞技术
protobuf串行化技术

9、数据写入成功的时候:
dataQueue.removeFirst(); //将数据队列中的第一个数据删除
ackQueue.addLast(one); //将此数据移动到确认队列的末尾
dataQueue.notifyAll(); //通知DataStreamer继续传输包

10、将数据实例化到磁盘的过程:
先把checksum和data之间的鸿沟去掉:
移动checksum数据到data数据之前
移动header数据到checksum之前

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

详细写入流程:
Client调用FileSystem的create()方法:
  1 FileSystem向NN发出请求,在NN的namespace里面创建一个新的文件,但是并不关联任何块。

  2 NN检查文件是否已经存在、操作权限。如果检查通过,NN记录新文件信息,并在某一个DN上创建数据块。

  3 返回FSDataOutputStream,将Client引导至该数据块执行写入操作。

Client调用输出流的write()方法:
  HDFS默认将每个数据块放置3份。FSDataOutputStream将数据首先写到第一节点,第一节点将数据包传送并写入第二节点,第二节点 –> 第三节点。

Client调用流的close()方法:
  flush缓冲区的数据包,block完成复制份数后,NN返回成功消息。

分类: hadoop1.x

综合描述:
客户端要向HDFS写数据,首先和NameNode通信,确认可以写文件并获得接受文件block的DataNode,然后客户端按顺序将文件逐个block上传给相应的DataNode,并由接受到block的DataNode负责向其他DataNode复制block副本。
hdfs-write
操作步骤:
1、Client调用FileSystem.create(filePath)方法,与NameNode进行RPC通信,check该路径的文件是否存在以及有没有权限创建该文件,如果都ok,就创建一个新文件,但是并不关联任何block,返回一个FSDataInputStream对象;(如果都不ok,就返回错误信息,所以要try-catch);
2、Client调用FSDataInputStream对象的write() 方法,会将第一个块写入第一个DataNode,第一个DataNode写完传给第二个节点,第二个写完传给第三个节点,当第三个节点写完返回一个ack packet给第二个节点,第二个返回一个ack packet给第一个节点,第一个节点返回ack packet给FSDataInputStream对象,意思标识第一个块写完,副本数为3,剩余的block依次这样写;
3、当向文件写入数据完成后,Client调用FSDataIputStream.close()方法,关闭输出流,flush缓存区的数据包;
4、再调用FileSystem.complete()方法,告诉NameNode节点写入成功。

3、写数据的流程

  • client将文件file1划分出blocks —— block1、block2、block3…
  • client向NN发出写block的请求 —— 文件file1的block1
  • NN响应client的请求 —— 指示client将file1的block1写到如下位置:

    • rack1 上的 dataNodeA、dataNodeB
    • rack2 上的 dataNodeC
  • client向dataNodeA发出写block的请求:

    • 文件file1的block1
    • 并告知还需将block写到dataNodeB和dataNodeC
  • dataNodeA一边将数据存入自身磁盘,一边向dataNodeB发出写block的请求,具体内容同上一步骤

  • dataNodeB一边将数据存入自身磁盘,一边向dataNodeC发出写block的请求,具体内容同上一步骤
  • dataNodeC完成block数据存储后,响应dataNodeB:

    • 告知自身对file1-block1的存储已经正常完成。
    • 自身同时存储元数据(file1,block1,block1start…)
  • dataNodeB接收到dataNodeC的响应后,响应dataNodeA:

    • 告知对file1-block1的存储已经正常完成。
    • 自身同时存储元数据(file1,block1,block1start..)
  • dataNodeA接收到dataNodeC的响应后,响应client。

  • dataNodeA、dataNodeB、dataNodeC在存储一个新的block后,会向NN发送报告,NN会及时更新file1-block1的元数据:
    • (fiel1,block1,replicationids)
    • replicationid1,dataNodeA
    • replicationid2,dataNodeB
    • replicationid3,dataNodeC

猜你喜欢

转载自blog.csdn.net/qq_16038125/article/details/80324902
今日推荐