HDFS 读写流程介绍

109 阅读5分钟

HDFS 架构

  1. Client:客户端
  • 切分文件。文件上传 HDFS 的时候,Client 将文件切分成一个一个的block,然后进行存储。
  • 与 NameNode 交互,获取文件的位置信息。
  • 与 DataNode 交互,读取/写入数据。
  • Client 提供一些命令来管理HDFS,比如启动/关闭HDFS目录及内容等。
  1. NameNode: 主节点,存储数据的元数据信息,不存储具体的数据。
  • 管理 HDFS 的命名空间
  • 管理数据块(block)映射信息
  • 配置副本策略
  • 处理客户端读写请求
  1. DataNode:数据节点,也成从节点。
  • 存储实际的数据块
  • 执行数据块的读/写操作
  1. Secondary NameNode:并非 NameNode 的热备。当 NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务 。
  • 辅助 NameNode,分担其工作量 。
  • 定期合并 Fsimage 和 Edits,并推送给 NameNode 。
  • 在紧急情况下,可辅助恢复 NameNode。

假如

文件:/home/hadoop/data/order.txt

文件大小:200M

block 大小:128M

HDFS 写数据

  1. Client 客户端发送上传请求,通过RPC与NameNode建立通信,NameNode检查该用户是否有上传权限、上传文件在HDFS上是否已经存在(重名文件),这两者有任意一个不满足则直接报错,如果都满足则返回给客户端一个可以上传文件的信息。
  2. Client 根据文件的大小进行切分,默认128M一个block,切分完成后给NameNode发送请求,告知第一个block块上传到哪些服务器。
  3. NameNode 收到请求后,根据网络拓扑图和机架感知以及副本机制进行文件分配,返回可用的 DataNode 地址列表。
  4. Client 收到 DataNode 地址后与 DataNode 服务器列表中的一个节点 A 进行通信(本质就是RPC调用),建立 Pipline,A 收到请求后会继续调用B,B再调用C,将整个Pipline建立完成,逐级返回给Client。
  5. Client 开始向A节点服务器上发送第一个block(先从磁盘读取数据然后放到本地内存中缓存),以 packet(数据包,64kb)为单位,A收到一个 packet 就会发送给B,然后B发送给C,A每传输完一个 packet 就会放入一个应答队列等待应答。
  6. 数据被分割成一个一个 packet 数据包在 Pipline 上传输,在 Pipline 反向传输中,逐个发送 ack(命令正确应答),最终由Pipline中第一个 DataNode节点A将 Pipline ack 发送给 Client。
  7. 当第一个 block 传输完成之后, Client 再次请求 NameNode上传第二个block,NameNode 重新选择三台DataNode返回给Client,继续重复4-6步骤,直到数据上传完成。
  8. Client 告诉NameNode任务完成。

HDFS 读数据

  1. Client 向 NameNode 发送读数据请求(RPC调用),即文件block的位置信息。
  2. NameNode 收到请求后检查用户是否有下载权限、文件是否存在。如果条件都满足则会视情况返回部分或全部的block列表,对于每一个block,NameNode都会返回含有block副本的DataNode地址(这些返回的DataNode地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DataNode 状态为 STALE,这样的排靠后)。
  3. Client 选取排序靠前的 DataNode 来读取block,如果客户端本身就是 DataNode,那么将从本地直接获取数据(短路读取特性)。
  4. 底层上本质是建立 Socket Stream(FSDataOutputStream),重复的调用父类 DataInputStream 的 read 方法,直到这个块上的数据读取完毕。
  5. 当读完第一批 block 列表后,若文件读取还没有结束,客户端会继续向 NameNode 获取下一批的 block 列表位置信息。
  6. 每读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的 DataNode 继续读。
  7. read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回数据的元数据信息,并不是直接返回请求块的数据。
  8. 最终读取到所有的 block 会合并成一个完整的最终文件。

HDFS 在读取文件的时候,如果其中一个块突然损坏了怎么办?

客户端读取完DataNode上的块之后会进行 checksum 验证,也就是把客户端读取到本地的块与HDFS上的原始块进行校验,如果发现校验结果不一致,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的 DataNode 继续读。

HDFS 在上传文件的时候,如果其中一个 DataNode 突然挂掉了怎么办?

客户端上传文件时与 DataNode 建立 pipline 管道,管道正向是 Client 向 DataNode 发送的数据包,管道反向是 DataNode 向 Client 发送 ack 确认。也就是正确接受到数据包之后发送一个已确认收到的应答,当 DataNode 突然挂掉,客户端收不到这个 DataNode 发送到 ack 确认,Client 会通知 NameNode,NameNode 检查该块的副本与规定的不符,NameNode 会通知DataNode去复制副本,并将挂掉的 DataNode 作下线处理,不再让它参与文件上传/下载。