HDFS上传文件流程
文件上传流程图如下 :

首先 , HDFS选用的是每启动一个线程 , 就传递一个块 , 然后接收到第一个块后的机器复制给其他机器 .
首先我们知道namenode的职责 :
- 管理整个文件系统的元数据 ( 目录树 文件和块对应信息 , dn信息)
- 响应整个客户端的所有请求 hdfs://node-1:9000
上传文件的流程
- 首先hdfs客户端通过RPC调用向nn发送请求上传文件1.txt
- 元数据根据请求信息查询元数据 , 判断是否可以上传
- 返回可以请求上传 , 响应给客户端
- 将数据的块(blk-1)[采用3副本]上传到元数据中
- 根据请求 , 并且结合dn信息返回3台可以用的dn的ip(dn1,dn2,dn3)
- nn返回上传副本的信息给客户端
- 客户端和dn1建立传输数据的管道(pipeline) , 与此同时 , dn1与dn2之间也建立传输数据的管道 , 直到最后一个为止
- 依次返回pipeline建立完毕信息 , 直到响应给客户端
- 传输数据包(packet) , 默认大小为64K , dn*把接收到的packet保存到指定的目录中 , 并且把packet继续往后发 , 直到最后一个
- 发送完毕后反方向追个返回ack应答 , 保证packet的安全稳定 , 直到返回给客户端
- 待第一块上传完毕 , 客户端按照上述流程走一遍 , 上传第二个块 , 从第4步开始 , 重新发起请求 , 寻找可用的dn位置
- 待所有块上传完毕 , 客户端把信息告知namenode , nn把信息同步到文件系统的元数据中
Q : 何为真正的上传文件成功 , 如果上传中pipeline断开 , 怎么办?
如果是客户端和dn之间断开 , 重新上传 ; 如果是dn之间断开 , hadoop认为只要有一个副本成功 , 那么此次上传就算成功 , 剩下不足的副本待上传完成由nn指定其他dn进行副本的复制工作 , 使得最终的副本数==设定的副本数
3副本策略

第一个副本 , 如果客户端所在的机器恰巧有datanode , 且datanode状态良好 , 磁盘未满 , 就将第一个副本放在此机器 ; 如果不满足 , 那么就找离客户端最近的一台机器作为第一个副本所在地 . 如果出现多个相同距离的 , 随机找即可.
tips: 这里所谓的近 : 不是空间距离上的远近 , 而是网络拓扑图中的远近 , 网络拓扑图中以经过的交换机个数作为距离
第二个副本 : 不同于第一个副本所在的机架的其他机架上随机找一个可用的
第三个副本 : 跟第二个同一个机架上的不同机器即可
如果副本数不是3, 假设副本数是2 , 副本数是5 甚至没有机架 , 第一个副本还是上述策略 , 其他的副本随机存储
理想的3副本策略图

HDFS下载文件流程
- Client向namenode发起RPC请求 , 确定请求文件block所在的位置
- nn的元数据会对请求进行判断 , 根据情况返回文件的部分或者全部blk列表 , 且每个blk , nn都会返回含有该blk副本的datanode地址
- 返回的dn地址 , 会按照集群拓扑结构得出dn与客户端的距离并进行排序 , 排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 STALE,这样的排靠后
- Client选取排序靠前的dn来读取blk , 若客户端本身就是dn , 那么直接从本地直接获取数据
- 底层上本质是建立Socket Stream(FSDataInputStream) , 重复的调用父类DataInputStream的read方法 , 知道这个块上的数据读取完毕
- 当读取完列表的blk之后 , 若文件读取还没有结束 , 客户端会继续向nn获取下一批的blk列表
- 读取完一个blk都会进行checksum验证 , 如果读取dn时出现错误 , 客户端会通知nn , 然后再从下一个拥有blk副本的dn继续读
- read方法是并行的读取blk信息 , 不是一块一块的读取 , nn只返回Client请求包含块的dn地址 , 并不返回数据
- 最终读取来所有的blk合并成一个完整的文件.
完整的文件下载流程图如下 :

2005



被折叠的 条评论
为什么被折叠?



