写数据流程

image.png

写流程

前提:副本数:3
写流程之前:会将修改的元数据edits文件,写入到edits_inprogress_xxxxxxxx中,SecondaryNameNode 负责定期合并 fsimageedits 文件,生成新的元数据快照。[[5.NameNode和SecondaryNameNode工作机制🔥]]

  1. 客户端向NameNode请求上传文件,比如说500M,系统会创建FSDataOutputStream并在内部初始化数据队列(data queue)确认队列(ack queue)
  2. NameNode确认可以上传,并获取到了FSDataOutputStream
  3. 请求上传第一个Block块。
  4. NameNode返回3个DataNode,表示可以用这三个节点来存块。[[#^e45f1c]]
  5. 然后客户端向FSDataOutputStream发送写指令,DataStreamer会和这3个DataNode建立Block的传输通道,处理数据对接中的快(dn1收到一个Packet就会传给dn2,dn2传给dn3)。
  6. 创建通道完成后,3节点会应答成功。
  7. 传输已Packet为单位的数据包,每个数据包64K,每次传输一个 Packet ,并进行校验,确保数据完整性。
  8. 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。
  9. 收到管道中的所有队列确认后,本次数据包才会将确认队列中删除。

    写流程故障处理

    如果在写入某个时发生了故障则会执行以下操作:

  10. 关闭本次管道。
  11. 把本次队列中的所有数据包都添加回数据队列的最前端。
  12. 删除已经传输完成的包。
  13. 从管线中删除故障的节点。
  14. 基于剩下的两个DataNode构造新的管道传输。
  15. 副本数不够的话让NameNode做自动副本恢复,达到副本数3为止。

    DataNode的选择

^e45f1c

对于常见情况,当复制因子为 3 时,HDFS 的放置策略是,如果写入器位于数据节点上,则将一个副本放在本地机器上,否则将一个副本放在与写入器位于同一机架中的随机数据节点上,另一个副本放在不同(远程)机架中的节点上,最后一个副本位于同一远程机架中的不同节点上。此策略会减少机架间写入流量,这通常会提高写入性能。机架故障的几率远小于节点故障的几率; 此策略不会影响数据可靠性和可用性保证。但是,它不会减少读取数据时使用的聚合网络带宽,因为块仅放置在两个唯一的机架中,而不是三个。使用此策略时,数据块的副本不会在机架之间均匀分布。两个副本位于一个机架的不同节点上,其余副本位于其他机架之一的节点上。此策略可在不影响数据可靠性或读取性能的情况下提高写入性能。
image.png|375

  • 一个副本放在本地机器上位于同一机架中的随机数据节点上
  • 另一个副本放在不同(远程)机架中的节点上。
  • 最后一个副本位于同一远程机架中的不同节点上
    防止:机房故障、机架故障、节点故障

    读数据流程

    image.png

    读流程

    1. 请求下载一个文件。
    2. NameNode 确认文件是否存在并检查用户权限,然后返回文件的元数据,包括该文件的块列表以及每个块存储在哪些 DataNode 上,并创建FSDataInputStream读取数据。
    3. 获取FSDataInputStream并向DataNode1请求下载blk1
    4. 传输数据,下载完成后进行数据完整性校验(CRC)。
    5. 需要等待blk1下载完成后,才可以下载blk2, 向DataNode2请求下载blk2,并进行数据完整性校验(CRC)。
    6. 完成。

      读流程故障

      如果在读取的过程中遇到了问题(datanode硬件故障):

    7. 记住故障的datanode,减少读取后续块。
    8. 会尝试从最近的另一个DataNode读取数据。

      源码

      org.apache.hadoop.hdfs.DFSInputStream#readWithStrategy

      image.png
      只对当前的InputStream对象进行锁定,这样就代表:

  • 同一client是串行读Datanode中的block
  • 不同的client可以并发读DataNode