网站首页 > 基础教程 正文
hdfs上传文件流程
HDFS(hadoop distributed file system)是一个分布式文件系统,具有横向扩展,高容错性等特点,当我们向hdfs上传文件时,到底发生了哪些事呢?
1.首先,客户端向namenode请求上传数据。
2.namenode收到客户端的请求后,会检查客户端请求的路径是否存在该文件,如果已存在,文件已存在,会抛出异常,一般为文件已存在,如果未存在,则返回可以上传。
3. 客户端收到可以上传的响应后,会把待上传的文件切块,(hadoop2.x默认块大小为128M);然后再次像namenode发送请求,上传第一个block块。
4.namenode根据相关算法,主要根据距离,返回特定的datanode。
5.客户端根据收到datanode节点信息,向datanode请求简历socket channel 连接
6. 由于hdfs默认的文件存储为3份,第一个datanode会和剩余的datanode建立连接通道,这个通道叫做pipe line
7. 向高端的datanode返回简历socket连接成功
8. 客户端收到连接建立后,等待数据发送
9. 客户端发送数据,发送的基本单元是packet,默认为64kb大小
10. datanode本地缓存,然后进行相关的数据校验,校验通过后,将packet发送给存储副本的datanode
11. 在完成第一个block后,后续的block重复上述步骤进行发送,直到所有的block都发送完毕。
hdfs api 写入流程
看完了上传流程,我们再来看下简单的api写入文件。
那么,上面简单的api操作,在系统内部,到底发生了哪些事情?
那么,下图将有助于你理解。
1.首先,调用客户端的对象DistributedFileSystem的create方法;
2.DistributedFileSystem会发起对namenode的一个RPC连接,请求创建一个文件,不包含关于block块的请求。namenode会执行各种各样的检查,确保要创建的文件不存在,并且客户端有创建文件的权限。如果检查通过,namenode会创建一个文件(在edits中),否则创建失败,客户端抛异常IOException。
3.DistributedFileSystem返回一个FSDataOutputStream对象给客户端用于写数据。FSDataOutputStream封装了一个DFSOutputStream对象负责客户端跟datanode以及namenode的通信。
4.FSDataOutputStream对象将数据切分为小的数据包packet(64kb),并写入到一个内部队列(“数据队列”)。DataStreamer会读取其中内容,并请求namenode返回一个datanode列表来存储当前block副本。列表中的datanode会形成管线,DataStreamer将数据包发送给管线中的第一个datanode,第一个datanode将接收到的数据发送给第二个datanode,第二个发送给第三个。。。
5.DFSOoutputStream维护着一个数据包的队列,这个数据包是需要写入到datanode中的,该队列称为确认队列。当一个数据包在管线中所有datanode中写入完成,就从ack队列中移除该数据包。队列是在客户端维护的。
6.如果在数据写入期间datanode发生故障,则执行以下操作
a、关闭管线,把确认队列中的所有包都添加回数据队列的最前端,以保证故障节点下游的datanode不会漏掉任何一个数据包。
b、为存储在另一正常datanode的当前数据块指定一个新的标志,并将该标志传送给namenode,以便故障datanode在恢复后可以删除存储的部分数据块。
c、如果在数据写入期间datanode发生故障,待确认消息队列迟迟得不到确认消息,这时会有一个超时时间,超过这个时间,从管线中删除故障数据节点并且把余下的数据块写入管线中另外两个正常的datanode(也就是这两个节点组成新的管线并且blockID的值要发生变化,另外注意正常的节点中包括之前上传的部分小的64K文件,所以需要对其进行一个统计,确认我现在数到第几个包了,避免重复提交)。namenode在检测到副本数量不足时,会在另一个节点上创建新的副本。
d、后续的数据块继续正常接受处理。
7.在一个块被写入期间可能会有多个datanode同时发生故障,但非常少见。只要设置了dfs.replication.min的副本数(默认为1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标副本数(dfs.replication默认值为3)。
8.如果有多个block,则会反复从步骤4开始执行。
9.当客户端完成了数据的传输,调用数据流的close方法。该方法将数据队列中的剩余数据包写到datanode的管线并等待管线的确认
10.客户端收到管线中所有正常datanode的确认消息后,通知namenode文件写完了。
11.客户端完成数据的写入后,对数据流调用close方法。该操作将剩余的所有数据包写入datanode管线,并在联系到namenode且发送文件写入完成信号之前,等待确认。
namenode已经知道文件由哪些块组成,所以它在返回成功前只需要等待数据块进行最小量的复制。
注意:如果在数据写入期间datanode发生故障,待确认消息队列迟迟得不到确认消息,这时会有一个超时时间,超过这个时间
文件写文件的时候只有一个客户端能写,保证数据上传成功
猜你喜欢
- 2024-11-17 第三篇 hadoop的核心概念&存取策略
- 2024-11-17 Java 17 的 I/O 基础 OutputStream 篇
- 2024-11-17 数据湖(十七):Flink与Iceberg整合DataStream API操作
- 2024-11-17 javaUDP协议DatagramPacket、DatagramSocket
- 2024-11-17 JavaSE---02(javase下载安装教程)
- 2024-11-17 每秒8.8亿次请求!Lindorm让数据存得起,看得见
- 2024-11-17 Java IO: 文件读写与数据流操作(java文件读取和写入实例)
- 2024-11-17 面试官:请说下适配器模式、代理模式和装饰者模式的不同
- 2024-11-17 HDFS和NFS的架构及原理(hdfs fs -ls)
- 2024-11-17 这篇文章过后,别说你不懂NIO(这篇文章告诉你答案)
- 最近发表
- 标签列表
-
- jsp (69)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- pythonif (86)
- location.href (69)
- dockerexec (65)
- tail-f (79)
- queryselectorall (63)
- location.search (79)
- bootstrap教程 (74)
- deletesql (62)
- linuxgzip (68)
- 字符串连接 (73)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)