Hadoop学习笔记10之HDFS写入时序分析

先画一个示意图:

【几个基本概念】

1.block

文件块

默认块大小:128M

最小块:1M

2.packet

64K

3.chunk

小块

512字节,必须能被packet整除

【代码分析】

使用Eclipse Junit测试和Debug 分析代码的代码段如下:

         @Test

         publicvoid putFile() throws Exception{

                   /**

                    * 通过Hadoop API创建文件

                    */

                  

                   Configurationconf = new Configuration();

                   conf.set("fs.defaultFS","hdfs://192.168.40.130:8020");

                   FileSystemfs = FileSystem.get(conf);

                   Pathp =new Path("/user/ctr/hadoop/mkFromWindows/hello.txt");

                   FSDataOutputStreamfos = fs.create(p);

                   fos.write("Hello,World".getBytes());

                   fos.close();

         }

【过程描述】

下文参考《Hadoop权威指南》

客户端通过对 DistributedFileSystem 对象调用 create()函数来创建文件。DistributedFileSystem 对 namenode 创建一个 RPC 调用,在文件系统的命名空间中创建一个新文件,此时该文件中还没有相应的数据块。namenode执行各种不同的检查以确保这个文件不存在,并且客户端有创建该文件的权限。如果这些检查翊通过,namenode就会为创建新文件记录一条记录;否则,文件创建失败并向客户端抛出一个IOException 异常 DistributedFileSystem 想客户端返回一个 FSDataOutputStream 对象,由此客户端可以开始写入数据。就像读取事件一样, FSDataOutputStream 封装一个 DFSoutPutstream 对象,该对象负责处理 datanode 和 namenode 之间的通信。在客户端写入数据时,DFSOutputStream 将它分成一个个的数据包,并写入内部队列,称为“数据队列” (data queue)。 DataStreamer 处理数据队列,它的责任是根据datanode 列表来要求 namenode 分配适合的新块来存储数据备份。这一组 datanode 构成一个管线,假设复本数为 3,所以管线中有 3 个节点。 DataStreamer 将数据包流式传输到管线中第 1 个datanode,该 datanode 存储数据包并将它发送到管线中的第 2 个 datanode。同样地,第 2 个 datanode 存储该数据包并且发送给管线中的第3。 DFSOutputStream 也维护着一个内部数据包队列来等待 datanode 的收到确认回执,称为“确认队列” (ack queue)。当收到管道中所有 datanode 确认信息后,该数据包才会从确认队列删除。如果在数据写入期间, datanode 发生故障,则执行以下操作,这对与写入数据的客户端是透明的。首先关闭管线,确认把队列中的任何数据包都添加回数据队列的最前端,以确保故障节点下游的 datanode 不会漏掉任何一个数据包。为存储在另一正常 datanode 的当前数据块指定一个新的标识,并将该标识传送给 namenode,以便故障 datanode 在恢复后可以删除存储的部分数据块。从管线中删除故障数据节点并且把余下的数据块写入管线中的两个正常的的datanode。 namenode 注意到块复本量不足时,会在另一个节点上创建一个新的复本。后续的数据块继续正常接受处理。在一个块被写入期间可能会有多个 datanode 同时发生故障,但非常少见。只要写入了dfs.replication.min复本数(默认为 1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标复本数( dfs.eplication的默认值为 3)。客户端完成数据的写入后,会对数据流调用 close()方法。该操作将剩余的所有数据包写入 datanode 管线中,并在联系 namenode 且发送文件写入完成信号之前,等待确认。

猜你喜欢

转载自blog.csdn.net/cskywit/article/details/80638973