目录
显示
写数据流程
写流程
前提:副本数:3
写流程之前:会将修改的元数据edits
文件,写入到edits_inprogress_xxxxxxxx
中,SecondaryNameNode
负责定期合并 fsimage
和 edits
文件,生成新的元数据快照。[[5.NameNode和SecondaryNameNode工作机制🔥]]
- 客户端向NameNode请求上传文件,比如说500M,系统会创建
FSDataOutputStream
并在内部初始化数据队列(data queue)
和确认队列(ack queue)
。 - NameNode确认可以上传,并获取到了
FSDataOutputStream
。 - 请求上传第一个Block块。
- NameNode返回3个DataNode,表示可以用这三个节点来存块。[[#^e45f1c]]
- 然后客户端向
FSDataOutputStream
发送写指令,DataStreamer
会和这3个DataNode建立Block的传输通道,处理数据对接中的快(dn1收到一个Packet就会传给dn2,dn2传给dn3)。 - 创建通道完成后,3节点会应答成功。
- 传输已Packet为单位的数据包,每个数据包
64K
,每次传输一个 Packet ,并进行校验,确保数据完整性。 - 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。
- 收到管道中的所有队列确认后,本次数据包才会将确认队列中删除。
写流程故障处理
如果在写入某个
块
时发生了故障则会执行以下操作: - 关闭本次管道。
- 把本次队列中的所有
数据包
都添加回数据队列的最前端。 - 删除已经传输完成的包。
- 从管线中删除故障的节点。
- 基于剩下的两个DataNode构造新的管道传输。
- 副本数不够的话让NameNode做自动副本恢复,达到副本数3为止。
DataNode的选择
^e45f1c
对于常见情况,当复制因子为 3 时,HDFS 的放置策略是,如果写入器位于数据节点上,则将一个副本放在本地机器上,否则将一个副本放在与写入器位于同一机架中的随机数据节点上,另一个副本放在不同(远程)机架中的节点上,最后一个副本位于同一远程机架中的不同节点上。
此策略会减少机架间写入流量,这通常会提高写入性能。机架故障的几率远小于节点故障的几率; 此策略不会影响数据可靠性和可用性保证。但是,它不会减少读取数据时使用的聚合网络带宽,因为块仅放置在两个唯一的机架中,而不是三个。使用此策略时,数据块的副本不会在机架之间均匀分布。两个副本位于一个机架的不同节点上,其余副本位于其他机架之一的节点上。此策略可在不影响数据可靠性或读取性能的情况下提高写入性能。
一个副本放在本地机器上
或位于同一机架中的随机数据节点上
。- 另一个副本放在不同(远程)机架中的节点上。
- 最后一个副本位于同一远程机架中的不同节点上
防止:机房故障、机架故障、节点故障读数据流程
读流程
- 请求下载一个文件。
NameNode
确认文件是否存在并检查用户权限,然后返回文件的元数据,包括该文件的块列表以及每个块存储在哪些DataNode
上,并创建FSDataInputStream
读取数据。- 获取
FSDataInputStream
并向DataNode1请求下载blk1
。 - 传输数据,下载完成后进行数据完整性校验(CRC)。
- 需要等待
blk1
下载完成后,才可以下载blk2
, 向DataNode2请求下载blk2
,并进行数据完整性校验(CRC)。 - 完成。
读流程故障
如果在读取的过程中遇到了问题(datanode硬件故障):
- 记住故障的datanode,减少读取后续块。
- 会尝试从最近的另一个DataNode读取数据。
源码
org.apache.hadoop.hdfs.DFSInputStream#readWithStrategy
- 同一client是
串行读
Datanode中的block - 不同的client可
以并发读
DataNode