一、HDFS角色以及职责

1.NameNode

NameNode是Hadoop分布式文件系统的核心,架构中的主角色

NameNode维护和管理文件系统元数据,包括名称空间目录树结构、文件和块的位置信息、访问权限等信息

基于以上原因, NameNode成为了访问HDFS的唯一入口。

HDFS工作流程与机制 - 图1

NameNode内部通过内存(如果服务器断电,内存数据全部消失)和磁盘文件两种方式管理元数据,其中磁盘上的元数据文件包括Fsimage内存元数据镜像文件和edits log(Journal)编辑日志

2.DataNode

DataNode是Hadoop HDFS中的从角色,负责具体的数据块存储

DataNode的数量决定了HDFS集群的整体数据存储能力。通过和NameNode配合维护着数据块

HDFS工作流程与机制 - 图2

3.主角色辅助角色: secondarynamenode

Secondary NameNode充当NameNode的辅助节点,但不能替代NameNode(当NameNode挂了以后,无法使用secondarynamenode充当NameNode)

主要是帮助主角色进行元数据文件的合并动作,可以通俗的理解为主角色的“性感小秘书”

HDFS工作流程与机制 - 图3

职责:

1.NameNode

  • NameNode仅存储HDFS的元数据:文件系统中所有文件的目录树,并跟踪整个集群中的文件, 不存储实际数据
  • NameNode知道HDFS中任何给定文件的块列表及其位置。使用此信息NameNode知道如何从块中构建文件
  • NameNode不持久化存储每个文件中各个块所在的datanode的位置信息,这些信息会在系统启动时从DataNode重建
  • NameNode是Hadoop集群中的单点故障(一旦NameNode挂掉之后,所有的读写请求都不存在了,不知道元元数据,访问不了,数据不会丢失(存在DataNode),但元数据以及目录树都没有了,无法定位到文件)
  • NameNode所在机器通常会配置有大量内存(RAM)

2.DataNode

  • DataNode负责最终数据块block的存储。是集群的从角色,也称为Slave
  • DataNode启动时,会将自己注册到NameNode并汇报自己负责持有的块列表
  • 当某个DataNode关闭时,不会影响数据的可用性。 NameNode将安排由其他DataNode管理的块进行副本复制
  • DataNode所在机器通常配置有大量的硬盘空间, 因为实际数据存储在DataNode中

二、HDFS写数据流程

完整流程图

HDFS工作流程与机制 - 图4

文件写入流程

在流程开始之前,要掌握一个词 - Pipeline(管道)

Pipeline(管道)- HDFS中上传文件写入数据过程中的一种数据传输方式

HDFS工作流程与机制 - 图5

根据上图,可以得知: 客户端将数据块写入第一个数据节点,第一个数据节点保存数据之后再将块复制到第二个数据节点,后者保存后将其复制到第三个数据节点。

为什么HDFS采用一个个进行数据传输,不采用同时并行传输?

因为数据以管道的方式, 顺序的沿着一个方向传输,这样能够充分利用每个机器的带宽,避免网络瓶颈和高延迟时的连接,最小化推送所有数据的延时

在线性推送模式下,每台机器所有的出口宽带都用于以最快的速度传输数据,而不是在多个接受者之间分配宽带。

以上的方式可能会出现数据丢失的情况,而为了解决数据丢失的问题,HDFS是这么解决的

HDFS工作流程与机制 - 图6

在每一个节点之间进行传输的时候,先返回ack,如果返回成功,再进行下一个节点的传输

ACK-确认字符,在数据通信中,接收方发给发送方的一种传输类控制字符。表示发来的数据已确认接收无误。

在HDFS pipeline管道传输数据的过程中,传输的反方向会进行ACK校验,确保数据传输安全。

默认的副本策略

默认副本存储策略是由BlockPlacementPolicyDefault指定(只要保证不再同一个机器上即可)

HDFS工作流程与机制 - 图7

完整流程描述

HDFS工作流程与机制 - 图8

以hadoop fs -put a.txt /这条命令为例,假设副本数为3:
  1. 客户端执行了命令后,会向NameNode发起上传请求,走的是RPC协议
  2. NameNode收到请求,执行各种检查判断:目标文件是否存在、父目录是否存在、客户端是否具有创建该文件的权限检查通过后 NameNode就会为本次请求记下一条记录并给客户端反馈是否可以上传的标记
  3. 客户端收到请求后,将文件进行切片(将a.txt切成了三片))。也可以理解成块(block)
  4. 客户端发起上传第一个block请求(块)
  5. 内部组件datastreamer请求NameNode挑选出适合存储数据副本的一组DataNode地址返回给客户端(3副本)
  6. 客户端和主机列表中第一个的主机建立pipeline,datastreamer将数据包流式传输到一个DataNode,第一个DataNode跟第二个DataNode建立pipeline,以此类推进行数据包的传输,形成一个客户端到三台主机的线性管道。
  7. 考虑到网络传输性能,客户端上传block的时候会再次切片,将block切成多个package(数据包,默认大小是64kb,一个个上传),所有的数据包到达DataNode的时候都会被缓存
  8. 每一次的传输DataNode都要及时的返回ack机制校验数据包是否成功,如果失败,重试。
  9. 直到第一个DataNode收到ack并给客户端进行写应答。
  10. 客户端收到写应答后,会传下一个package
  11. 重复这个过程,直到所有的package传输完成,三台主机会将缓存中的数据包合成block(块),再落盘。
  12. 之后上传第二个第三个block
  13. 当所有的block全部传输完成之后,客户端会向NameNode汇报上传完毕
  14. NameNode收到请求之后会更新元数据。