持续更新大数据文章…
1. HDFS写入数据流程 ⭐️1.1 宏观流程HDFS写入数据流程是指:用户存储数据到 HDFS 上
客户端有一个文件:
- 名称为:user.log
- 大小为 :258MB
现在需要把文件 user.log 上传到 HDFS
具体宏观步骤是:
- 发送上传文件请求给 HDFS (上传命令:hdfs dfs -put user.log /huoborn),HDFS 接收到客户端的请求,并且判断上传命令的准确性。
- RPC 远程调用 NameNode 的 create() 方法。
- 调用 NameNode 的 create() 方法之后,NameNode 会检查请求用户是否有权限进行上传 *** 作。
- NameNode 的 create() 方法开始验证请求是否可以通过
- 如果请求不通过,抛出异常
- 如果请求通过,返回成功,并且会创建该文件的映射(entry对象)对象到 NameNode 的本地磁盘上
- 请求结果返回给客户端
- 如果结果为 false ,请求不通过,禁止上传。
- 如果结果为 true,请求通过,给客户端创建一个输出流FSDataOutPutStream
- 客户端把文件拆分成数据块,开始上传,先询问 NameNode, Block1 应该存放在哪个 DataNode 上
- 返回 Block1 与 DataNode 的映射信息给客户端,告诉客户端 Block1 存放在哪个 DataNode 上
- 根据返回的信息,存储 Block1 到对应 DataNode,并且让 HDFS 创建 DataNode 管道(通过Socket连接管道)
- 把 Block1 拆分为更小的存储单元 Packet(64K)
- Packet 像水流一样经过管道传输到 DataNode 上
- 直到 Block1 拆分成的 Packet 全部传输到 DataNode 上,并且 DataNode 上对应的 Packet 又重新组成 Block1
- 关闭为 Block1 创建的管道,开始准备传输 Block2
- 客户端询问 NameNode, Block2 应该存放在哪个 DataNode 上
- 返回 Block2 与 NameNode 的映射信息给客户端,告诉客户端 Block1 存放在哪个 DataNode 上
- 根据返回的信息,存储 Block2 到对应 DataNode,并且让 HDFS 创建 DataNode 管道(通过Socket连接管道)
- 把 Block2 拆分为更小的存储单元 Packet(64K)
- Packet 像水流一样经过管道传输到 DataNode 上
- 直到 Block2 拆分成的 Packet 全部传输到 DataNode 上,并且 DataNode 上对应的 Packet 又重新组成 Block2
- 关闭为 Block2 创建的管道,开始准备传输 Block3
- 依次重复,知道全部的数据块都存储到对应的 DataNode 上
- 集群启动之后,NameNode 的文件映射(entry对象)对象删除 数据块与 DataNode 的信息,该消息不保存到 NameNode 的本地磁盘上,而是根据心跳机制动态变换。
客户端有一个文件:
- 名称为:user.log
- 大小为 :258MB
现在需要把文件 user.log 上传到 HDFS
具体微观步骤是:
-
文件user.log 被 IO 读取到内存
-
user.log 被读成更小的单元 chunk(512 bytes)、checksum(4 bytes)
-
一个chunk(512 bytes)和一个checksum(4 bytes)组合和在一起
-
127个==chunk(512 bytes)、checksum(4 bytes)==对被封装成 Packet(64KB)
-
Packet 是要被发到对应的 DataNode上,但是生产 Packet 速度与发送给 DataNode 速度不对等,为了防止 Packet堵塞,把 Packet 放到队列上,队列的特性是先进先出。这里是类似于生产者-消费者模式。
-
为了防止 Packet传输出错,HDFS 有一个 DataStreamer
-
Packet 开始发送到对应的 DataNode 上
-
DataStreamer 开始工作
-
DataStreamer 从 DataQueue队列 拿出一个 Packet
-
DataStreamer 把拿到的 Packet 会备份一份,然后把其中一份发给输出流,这个 Packet 会发到 DataNode1 上
-
DataStreamer 把另一份 Packet 挂载到 AckQueue队列 上
-
-
当 DataNode(第n个)接收到Packet,之后,DataNode(第n个)会给DataNode(第n-1个)一个ACk应答,然后这个应答会一直往前面的 DataNode 传送直到被ResponseProcess接收,ResponseProcess接收之后就会删除挂载到AckQueue队列上面与这个应答相对应的Packet。同样的,当DataNode(第3个)接收到Packet4之后,DataNode(第3个)会给DataNode(第2个)一个ACK应答,DataNode(第2个)会给DataNode(第1个)一个ACK应答,DataNode(第1个)会告诉ResponseProcess,Packet4已经被接受,这个时候ResponseProcess就会被挂载到 AckQueue队列上面的Packet4删除
-
如果 Packet5 传输错误,那么挂载到 AckQueue队列 上的 Packet5 就会被 DataStreamer 转移到 DataQueue队列 的头部,然后DataStreamer 继续备份一份 Packet5 ,一份发送给输出流重新再一次给 DataNode 传输 Packet5 ,一份暂时挂载到 AckQueue队列 上
-
直到对应的 DataNode 上积累了 128MB 的Packet(数据块大小默认是128MB),这样就完成了一个数据块的传输,接着传输下一波数据块
-
重复以上步骤,chunk+checksum组成Packet发送给对应的DataNode ,直到对应的每个 DataNode 又积累了 128MB 的Packet(数据块大小默认是128MB),这样就又完成了一个数据块的传输。
-
重复,直到数据块全部传输完成
补充:
如果传输过程当中,有一个DataNode出现故障,那么其他的DataNode就会代替出现故障的DataNode继续接收Packte,接收完毕之后,剩余的DataNode与NameNode进行心跳,NN知道哪个DataNode出现故障之后就会做出对应的措施
下期讲解 HDFS_10_Packet......
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)