Wetts's blog

Stay Hungry, Stay Foolish.

0%

HDFS

HDFS(Hadoop Distributed File System,Hadoop 分布式文件系统)

相关概念

在传统的文件系统中,为了提高磁盘读写效率,一般以数据块为单位,而不是以字节为单位。比如,机械式硬盘(磁盘的一种)包含了磁头和转动部件,在读取数据时有一个寻道的过程,通过转动盘片和移动磁头的位置,来找到数据在机械式硬盘中的存储位置,然后才能进行读写。在 I/O 开销中,机械式硬盘的寻址时间是最耗时的部分,一旦找到第条记录,剩下的顺序读取效率是非常高的。因此,以块为单位读写数据,可以把磁盘寻道时间分摊到大量数据中。

HDFS 也同样采用了块的概念,默认的一个块大小是 64 MB。

当客户端需要访问一个文件时,首先从名称节点获得组成这个文件的数据块的位置列表,然后根据位置列表获取实际存储各个数据块的数据节点的位置,最后数据节点根据数据块信息在本地 Linux 文件系统中找到对应的文件,并把数据返回给客户端。

名称节点

名称节点(NameNode)负责管理分布式文件系统的命名空间(Namespace),保存了两个核心的数据结构,即 FsImage 和 EditLog。

  • FsImage:维护文件系统树以及文件树中所有的文件和文件夹的元数据。
  • EditLog:记录了所有针对文件的创建、删除、重命名等操作。

名称节点的数据结构

名称节点记录了每个文件中各个块所在的数据节点的位置信息,但是并不持久化存储这些信息,而是在系统每次启动时扫描所有数据节点重构得到这些信息。

数据节点

数据节点(DataNode)是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者名称节点的调度来进行数据的存储和检索,并且向名称节点定期发送自己所存储的块的列表。每个数据节点中的数据会被保存在各自节点的本地Linux文件系统中。

第二名称节点

在名称节点运行期间,HDFS会不断发生更新操作,这些更新操作都是直接被写人到 EditLog 文件,因此 EditLog 文件也会逐渐变大。在名称节点运行期间,不断变大的 EditLog 文件通常对于系统性能不会产生显著影响,但是当名称节点重启时,需要将 FsImage 加载到内存中,然后逐条执行 EditLog 中的记录,使得 FsImage 保持最新。可想而知,如果 EditLog 很大,就会导致整个过程变得非常缓慢,使得名称节点在启动过程中长期处于“安全模式”,无法正常对外提供写操作,影响了用户的使用。

为了有效解决 EditLog 逐渐变大带来的问题,HDFS 在设计中采用了第二名称节点(Secondary NameNode)。第二名称节点是 HDFS 架构的一个重要组成部分,具有两个方面的功能:

  • 首先,可以完成 EditLog 与 Fslmage 的合并操作,减小 EditLog 文件大小,缩短名称节点重启时间;
  • 其次,可以作为名称节点的“检查点”,保存名称节点中的元数据信息。

具体如下:

  1. EditLog 与 Fslmage 的合并操作。每隔一段时间,第二名称节点会和名称节点通信,请求其停止使用 EditLog 文件(这里假设这个时刻为 t),暂时将新到达的写操作添加到一个新的文件 EditLog.new 中。然后,第二名称节点把名称节点中的 FsImage 文件和 EditLog 文件拉回到本地,再加载到内存中;对二者执行合并操作,即在内存中逐条执行 EditLog 中的操作,使得 FsImage 保持最新。合并结束后,第二名称节点会把合并后得到的最新的 FsImage 文件发送到名称节点。名称节点收到后,会用最新的 FsImage 文件去替换旧的 FsImage 文件,同时用 EditLog.new 文件去替换 EditLog 文件(这里假设这个时刻为 t2),从而减小了,EditLog 文件的大小。
  2. 作为名称节点的“检查点”。从上面的合并过程可以看出,第二名称节点会定期和名称节点通信,从名称节点获取 FsImage 文件和 EditLog 文件,执行合并操作得到新的 FsImage 文件。从这个角度来讲,第二名称节点相当于为名称节点设置了一个“检查点”,周期性地备份名称节点中的元数据信息,当名称节点发生故障时,就可以用第二名称节点中记录的元数据信息进行系统恢复。但是,在第二名称节点上合并操作得到的新的 FsImage 文件是合并操作发生时(即 t1 时刻)HDFS 记录的元数据信息,并没有包含 t1 时刻和 t2 时刻期间发生的更新操作,如果名称节点在 t1 时刻和 t2 时刻期间发生故障,系统就会丢失部分元数据信息,在 HDFS 的设计中,也并不支持把系统直接切换到第二名称节点,因此从这个角度来讲,第二名称节点只是起到了名称节点的“检查点”作用,并不能起到“热备份”作用。即使有了第二名称节点的存在,当名称节点发生故障时,系统还是有可能会丢失部分元数据信息的。

第二名称节点工作过程示意图

HDFS 体系结构

概述

HDFS的体系结构

HDFS 命名控件管理

HDFS 的命名空间包含目录、文件和块。命名空间管理是指命名空间支持对 HDFS 中的目录、文件和块做类似文件系统的创建、修改、删除等基本操作。在当前的 HDFS 体系结构中,在整个 HDFS 集群中只有一个命名空间,并且只有唯一一个名称节点,该节点负责对这个命名空间进行管理。

HDFS 使用的是传统的分级文件体系,因此用户可以像使用普通文件系统样,创建、删除目录和文件,在目录间转移文件、重命名文件等。但是,HDFS 还没有实现磁盘配额和文件访问权限等功能,也不支持文件的硬连接和软连接(快捷方式)。

通信协议

HDFS 是一个部署在集群上的分布式文件系统,因此很多数据需要通过网络进行传输。所有的 HDFS 通信协议都是构建在 TCP/IP 协议基础之上的。客户端通过一个可配置的端口向名称节点主动发起 TCP 连,并使用客户端协议与名称节点进行交互。名称节点和数据节点之间则使用数据节点协议进行交互。客户端与数据节点的交互是通过 RPC(Remote Procedure Call)来实现的。在设计上,名称节点不会主动发起 RPC,而是响应来自客户端和数据节点的 RPC 请求。

HDFS 体系结构的局限性

HDFS只设置唯一一个名称节点,这样做虽然大大简化了系统设计,但也带来了一些明显的局限性,具体如下。

  1. 命名空间的限制。名称节点是保存在内存中的,因此名称节点能够容纳对象(文件、块)的个数会受到内存空间大小的限制。
  2. 性能的瓶颈。整个分布式文件系统的吞吐量受限于单个名称节点的吞吐量。
  3. 隔离问题。由于集群中只有一个名称节点,只有一个命名空间,因此无法对不同应用程序进行隔离。
  4. 集群的可用性。一旦这个唯一的名称节点发生故障,会导致整个集群变得不可用。

HDFS 的存储原理

数据的冗余存储

HDFS 采用了多副本方式对数据进行冗余存储,通常一个数据块的多个副本会被分布到不同的数据节点上。

HDFS数据块多副本存储

多副本方式具有以下 3 个优点:

  1. 加快数据传输速度。当多个客户端需要同时访问同个文件时,可以让各个客户端分别从不同的数据块副本中读取数据,这就大大加快了数据传输速度。
  2. 容易检查数据错误。HDFS 的数据节点之间通过网络传输数据,采用多个副本可以很容易判断数据传输是否出错。
  3. 保证数据的可靠性。即使某个数据节点出现故障失效,也不会造成数据丢失。

数据存取策略

数据存放

HDFS 默认的冗余复制因子是 3,每一个文件块会被同时保存到 3 个地方,其中,有两份副本放在同一个机架的不同机器上面,第三个副本放在不同机架的机器上面,这样既可以保证机架发生异常时的数据恢复,也可以提高数据读写性能(同机架内带宽高)。一般而言,HDFS 副本的放置策略如下:

  1. 如果是在集群内发起写操作请求,则把第一个副本放置在发起写操作请求的数据节点上,实现就近写入数据。如果是来自集群外部的写操作请求,则从集群内部挑选一台磁盘不太满、CPU 不太忙的数据节点,作为第一个副本的存放地。
  2. 第二个副本会被放置在与第一个副本不同的机架的数据节点上。
  3. 第三个副本会被放置在与第一个副本相同的机架的其他节点上。
  4. 如果还有更多的副本,则继续从集群中随机选择数据节点进行存放。

数据读取

HDFS 提供了一个 API 可以确定一个数据节点所属的机架 ID,客户端也可以调用 API 获取自已所属的机架 ID。当客户端读取数据时,从名称节点获得数据块不同副本的存放位置列表,列表中包含了副本所在的数据节点,可以调用 API 来确定客户端和这些数据节点所属的机架 ID。当发现某个数据块副本对应的机架 ID 和客户端对应的机架 ID 相同时,就优先选择该副本读取数据,如果没有发现,就随机选择-个副本读取数据。

数据复制

HDFS 的数据复制采用了流水线复制的策略,大大提高了数据复制过程的效率。当客户端要往 HDFS 中写入一个文件时,这个文件会首先被写入本地,并被切分成若千个块,每个块的大小是由 HDFS 的设定值来决定的。每个块都向 HDFS 集群中的名称节点发起写请求,名称节点会根据系统中各个数据节点的使用情况,选择一个数据节点列表返回给客户端,然后客户端就把数据首先写入列表中的第一个数据节点,同时把列表传给第一个数据节点,当第一个数据节点接收到 4 KB 数据的时候,写入本地,并且向列表中的第二个数据节点发起连接请求,把自己已经接收到的 4 KB 数据和列表传给第二个数据节点,当第二个数据节点接收到 4 KB 数据的时候,写人本地,并且向列表中的第三个数据节点发起连接请求,依次类推,列表中的多个数据节点形成一条数据复制的流水线。最后,当文件写完的时候,数据复制也同时完成。

数据错误与恢复

名称节点出错

Hadoop 采用两种机制来确保名称节点的安全:

  • 第一,把名称节点上的元数据信息同步存储到其他文件系统(比如远程挂载的网络文件系统 NFS)中;
  • 第二,运行一个第二名称节点,当名称节点宕机以后,可以把第二名称节点作为一种弥补措施,利用第二名称节点中的元数据信息进行系统恢复。

数据节点出错

每个数据节点会定期向名称节点发送“心跳”信息,向名称节点报告自己的状态。当数据节点发生故障,或者网络发生断网时,名称节点就无法收到来自一些数据节点的“心跳”信息,这时这些数据节点就会被标记为“宕机”,节点上面的所有数据都会被标记为“不可读”,名称节点不会再给它们发送任何 IO 请求。

这时,有可能出现一种情形,即由于些数据节点的不可用,会导致一些数据块的副本数量小于冗余因子。名称节点会定期检查这种情况,一旦发现某个数据块的副本数量小于冗余因子,就会启动数据冗余复制,为它生成新的副本。HDFS 与其他分布式文件系统的最大区别就是可以调整冗余数据的位置。

数据出错

网络传输和磁盘错误等因素都会造成数据错误。客户端在读取到数据后,会采用 md5 和 sha1 对数据块进行校验,以确定读取到正确的数据。在文件被创建时,客户端就会对每一个文件块进行信息摘录,并把这些信息写人同一个路径的隐藏文件里面。当客户端读取文件的时候,会先读取该信息文件,然后利用该信息文件对每个读取的数据块进行校验,如果校验出错,客户端就会请求到另外一个数据节点读取该文件块,并且向名称节点报告这个文件块有错误,名称节点会定期检查并且重新复制这个块。

HDFS 的数据读写过程

读数据的过程

HDFS读数据的过程

写数据的过程

HDFS写数据的过程