HDFS(Hadoop Distributed File System)是Hadoop核心组成之一,是分布式计算中数据存储管理的基础,被设计成适合运行在通用硬件上的分布式文件系统。是一个块结构的文件系统,其中每个文件被划分为预定大小的块。这些块存储在一台或多台计算机的集群中。 HDFS可以部署在支持Java的各种机器上。虽然可以在一台机器上运行多个数据节点,但在实际世界中,这些数据节点分布在各种机器上。总的来说,HDFS架构中有两类节点,一类是NameNode,又叫“元数据节点”,另一类是DataNode,又叫“数据节点”,分别执行Master和Worker的具体任务。HDFS是一个(Master/Slave)体系结构,“一次写入,多次读取”。HDFS的设计思想:分而治之—将大文件、大批量文件分布式存放在大量独立的机器上。架构见下图:

NameNode是Apache Hadoop HDFS架构中的主节点,用于维护和管理DataNodes(从属节点)上的块。 NameNode 是一个非常可用的服务器,它管理文件系统命名空间并控制客户端对文件的访问。我将在我的下一篇博客中讨论Apache Hadoop HDFS的这个高可用性特性。HDFS架构的构建方式是,用户数据永远不会驻留在NameNode上。数据仅驻留在数据节点上。
数据节点是HDFS中的从属节点。与NameNode不同,DataNode是一种商品硬件,即一种非昂贵的系统,质量不高或可用性不高。DataNode 是一个块服务器,用于将数据存储在本地文件 ext3 或 ext4 中。
它们定期向 NameNode 发送心跳以报告 HDFS 的整体运行状况,默认情况下,此频率设置为 3 秒
除了这两个守护进程之外,还有第三个守护进程或一个名为 Secondary NameNode 的进程。辅助名称节点与主名称节点同时工作,作为帮助程序守护程序。 不要混淆辅助名称节点是备份名称节点,因为它不是。

因此,辅助名称节点在HDFS中执行常规检查点。因此,它也被称为CheckpointNode。
现在,正如我们所知,HDFS中的数据作为块分散在DataNode上。让我们来看看什么是块,它是如何形成的?
块只不过是硬盘驱动器上存储数据的最小连续位置。通常,在任何文件系统中,您都将数据存储为块的集合。类似地,HDFS将每个文件存储为分散在整个Apache Hadoop集群中的块。在Apache Hadoop 2中,每个块的默认大小为128 MB。x(Apache Hadoop 1.x中为64 MB),您可以根据需要进行配置。

在HDFS中,每个文件不必以配置的块大小(128 MB,256 MB等)的精确倍数存储。让我们举个例子,我有一个大小为 514 MB 的文件“example.txt”,如上图所示。假设我们使用块大小的默认配置,即 128 MB。那么,将创建多少个块?5、对。 第一个四个块将为 128 MB。但是,最后一个块的大小仅为 2 MB。
现在,您一定在想为什么我们需要如此大的块大小,即 128 MB?
好吧,每当我们谈论HDFS时,我们都会谈论庞大的数据集,即TB和PB级的数据。如果我们的块大小为 4 KB(就像在 Linux 文件系统中一样),TB和PB级的数据分解将产生非常多的数据块及元数据。管理这些块和元数据将产生巨大的开销,这是我们不希望看到的。
HDFS提供了一种可靠的方法,可以在分布式环境中将大量数据存储为数据块。还会复制这些块以提供容错能力。默认复制因子为 3,同样可配置。因此,如下图所示,每个块被复制三次并存储在不同的 DataNode 上(考虑默认复制因子):

因此,如果您使用默认配置在 HDFS 中存储 128 MB 的文件,您最终将占用 384 MB (3*128 MB) 的空间,因为这些块将被复制三次,并且每个副本将驻留在不同的 DataNode 上。
注意:NameNode 定期从 DataNode 收集块报告,以维护复制因子。因此,每当块过度复制或复制不足时,NameNode 都会根据需要删除或添加副本。

无论如何,继续前进,让我们更多地讨论HDFS如何放置副本以及什么是机架感知?同样,NameNode 还确保所有副本不会存储在同一个机架或单个机架上。它遵循内置的机架感知算法,以减少延迟并提供容错能力。考虑到复制因子为 3,机架感知算法表示,块的第一个副本将存储在本地机架上,接下来的两个副本将存储在不同的(远程)机架上,但存储在该(远程)机架内的不同 DataNode 上,如上图所示。如果有更多副本,则其余副本将放置在随机 DataNode 上,前提是同一机架上驻留的副本不超过两个(如果可能)。

所以,现在你会想为什么我们需要机架感知算法?原因是:
现在我们来谈谈数据读/写操作是如何在HDFS上执行的。HDFS遵循“一次写 – 多次阅读”的理念。因此,您无法编辑已存储在 HDFS 中的文件。但是,您可以通过重新打开文件来追加新数据。
假设 HDFS 客户端想要写入一个名为“example.txt”的文件,大小为 248 MB。

假设系统块大小配置为 128 MB(默认值)。因此,客户端会将文件“example.txt”分成 2 个块 – 一个 128 MB(块 A)和另一个 120 MB(块 B)。
现在,每当数据写入HDFS时,将遵循以下协议:

在写入块之前,客户端确认每个 IP 列表中存在的数据节点是否已准备好接收数据。 在此过程中,客户端通过连接该块的相应列表中的各个 DataNode 来为每个块创建一个管道。让我们考虑块 A。NameNode 提供的数据节点列表为:
对于块 A,列表 A = {DataNode 1 的 IP、DataNode 4 的 IP、DataNode 6 的 IP}。

因此,对于块 A,客户端将执行以下步骤来创建管道:
创建管道后,客户端会将数据推送到管道中。现在,不要忘记在HDFS中,数据是根据复制因子复制的。因此,这里的块 A 将存储到三个数据节点,因为假设复制因子为 3。继续,客户端将仅将块 (A) 复制到 DataNode 1。复制始终由 DataNode 按顺序完成。

因此,在复制期间将执行以下步骤:
一旦将块复制到所有三个数据节点中,将进行一系列确认,以确保客户端和 NameNode 数据已成功写入。然后,客户端最终将关闭管道以结束 TCP 会话。
如下图所示,确认以相反的顺序发生,即从 DataNode 6 到 4,然后到 1。最后,DataNode 1 会将三个确认(包括它自己的)推送到管道中,并将其发送到客户端。客户端将通知 NameNode 数据已成功写入。NameNode 将更新其元数据,客户端将关闭管道。

同样,区块 B 也将与区块 A 并行复制到数据节点中。因此,这里需要注意以下事项:

如上图所示,每个块(A 和 B)形成了两个管道。以下是针对各自管道中的每个块发生的操作流:
HDFS Read架构相对容易理解。让我们再次举上面的例子,HDFS客户端现在想要读取文件“example.txt”。

现在,读取文件时将执行以下步骤:
在为客户端的读取请求提供服务时,HDFS 会选择离客户端最近的副本。这减少了读取延迟和带宽消耗。因此,如果可能,将选择与读取器节点位于同一机架上的复制副本。