HDFS-原理

本文详述HDFS的读写操作流程,包括客户端如何与NameNode交互以上传和下载文件,NameNode如何决定数据块的存储位置,以及HDFS如何平衡数据分布和处理故障。同时介绍了distcp并行复制工具和Balancer工具的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 写操作

客户端要向HDFS写数据,首先要跟Namenode通信以确认可以写文件并获得接收文件block的Datanode,然后,客户端按顺序将文件逐个block传递给相应Datanode,并由接收到block的Datanode负责向其他Datanode复制block的副本。

上述写步骤的详细流程:

  1. Client向NameNode请求上传文件(如test.txt);
  2. NameNode检查目标文件是否已存在,父目录是否已存在;
  3. NameNode返回是否可以上传;
  4. Client请求第一个block该传输到那些DataNode服务器上;
  5. NameNode查询可用的DataNode信息;
  6. NameNode返回三个可用的DataNode:node1,node2,node3;
  7. Client请求返回的三台DataNode中的一台node1上传数据(本质上是一个RPC调用,建立Pipeline);
  8. node1收到请求会继续调用node2,然后node2调用node3,将整个pipeline建立完成,逐级返回客户端;
  9. Client开始往node1上传block(副本为3个,先从磁盘读取数据放到一个本地内存缓存),以packet为单位,node1收到一个packet就会传给node2,node2传给node3;;这种写数据的方式呈流水线的形式。
  10. 最后一个DataNode成功存储之后会返回一个ack packet,在pipeline里传递至Client,在Client内部维护着"ack queue",成功收到DataNode返回的ack packet后会从"ack queue"移除相应的packet。
  11. 如果传输过程中,有某个DataNode出现了故障,那么当前的pipeline会被关闭,
  12. 出现故障的DataNode会从当前的pipeline中移除,将ack queue中的block放入data queue的开始(防止丢包),当前的block在已写入的DataNode中被NameNode赋予新的标示从而使错误节点重启后能够察觉其数据块是过时的,会被删除。剩余的block会继续在剩下的DataNode中继续以pipeline的形式传输,同时NameNode会被通知此block副本数不足,将会分配一个新的DataNode,保持副本设定的数量。

2. 读操作

客户端将要读取的文件路径发送给NameNode,NameNode获取文件的元信息(主要是block的存放位置信息)返回给客户端,客户端根据返回的信息找到相应DataNode逐个获取文件的block并在客户端本地进行数据追加合并从而获得整个文件。

  1. Client向NameNode发送读取文件test.txt请求;
  2. NameNode查询元数据信息,视情况返回文件的部分或者全部block列表,对于每个block,NameNode都会返回有该block副本的DataNode地址;
  3. Client会选取距离的DataNode来读取block;如果客户端本身就是DataNode,那么将从本地直接获取数据;
  4. 读取完当前block的数据后,关闭与当前的DataNode连接,并为读取下一个block寻找最佳的DataNode;
  5. 当读完列表的block后,且文件读取还没有结束,Client会继续向Namenode获取下一批的block列表;
  6. 读取完一个block都会进行checksum验证,如果读取DataNode时出现错误,Client会通知NameNode,然后再从下一个拥有该block副本的DataNode继续读。

3. NameNode如何决定副本存在哪个DataNode?

HDFS集群的物理拓扑如上图所示:读数据尽量在一个机架上读,在不同的机架之间读数据要通过交换机,延迟比较高。同一个机架内两个节点同时出故障的概率要比不同机架内两个节点出故障高很多。因为同一个机架的两个节点共享一个交换机,物理上许多东西都是共享的,那么同时出故障概率要高。

HDFS的副本的存放策略是可靠性、写带宽、读带宽之间的权衡。默认策略如下:

  • 第一个副本放在客户端相同的机器上,如果机器在集群之外,随机选择一个(但是会尽可能选择容量不是太慢或者当前操作太繁忙的)
  • 第二个副本随机放在不同于第一个副本的机架上。
  • 第三个副本放在跟第二个副本同一机架上,但是不同的节点上,满足条件的节点中随机选择。
  • 更多的副本在整个集群上随机选择,虽然会尽量避免太多副本在同一机架上。 
    副本的位置确定之后,在建立写入管道的时候,会考虑网络拓扑结构。下面是可能的一个存放策略:

这样选择很好的平衡了可靠性、读写性能

  • 可靠性:Block分布在两个机架上
  • 写带宽:写入管道的过程只需要跨越一个交换机
  • 读带宽:可以从两个机架中任选一个读取

为什么不把三个副本放在三个不同的机架上?这样容错能力岂不是更强?

上面已经说了不同机架之间的读写效率低,因为要通过一个交换机,而交换机的速率可能有瓶颈。所以把三个副本放在两个不同的机架上基于性能和可靠性的一个折中。

4. Hadoop节点距离

在读取和写入的过程中,NameNode在分配DataNode的时候,会考虑节点之间的距离。HDFS中,距离没有 
采用带宽来衡量,因为实际中很难准确度量两台机器之间的带宽。 
Hadoop把机器之间的拓扑结构组织成树结构,并且用到达公共父节点所需跳转数之和作为距离。事实上这是一个距离矩阵的例子。下面的例子简明地说明了距离的计算:

同一数据中心,同一机架,同一节点距离为0

同一数据中心,同一机架,不同节点距离为2

同一数据中心,不同机架,不同节点距离为4

不同数据中心,不同机架,不同节点距离为6

Hadoop集群的拓扑结构需要手动配置,如果没配置,Hadoop默认所有节点位于同一个数据中心的同一机架上。

5. distcp并行复制

如果需要并行处理文件,需要自己编写应用。Hadoop提供的distcp工具用于并行导入数据到Hadoop或者从Hadoop导出。distcp是底层使用MapReduce实现,只有map实现,没有reduce。在map中并行复制文件。 distcp尽可能在map之间平均分配文件。这样的操作常用于在两个集群之间复制数据,update参数表示只同步被更新过的数据,delete会删除目标目录中存在,但是源目录不存在的文件。

6. 平衡HDFS集群

在distcp工具中,如果我们指定map数量为1,不仅速度很慢,每个Block第一个副本将全部落到运行这个唯一map的节点上,直到磁盘溢出。因此使用distcp的时候,最好使用默认的map数量,即20. 
HDFS在Block均匀分布在各个节点上的时候工作得最好,如果没有办法在作业中尽量保持集群平衡,例如为了限制map数量(以便其他节点可以被别的作业使用),那么可以使用balancer工具来调整集群的Block分布。

参考:[Hadoop] HDFS 详解一(原理篇)   HDFS写入和读取流程

 

转载于:https://my.oschina.net/liyurong/blog/3042480

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值