**
引言:
**
在当今数据爆炸的时代,存储和管理大规模数据成为了许多组织面临的重要挑战。为了解决这一挑战,分布式文件系统应运而生。Hadoop分布式文件系统(HDFS)作为Apache Hadoop生态系统的核心组件之一,已经成为处理大数据的事实标准之一。它以其高可靠性、高容错性和高可用性等特点,在大规模数据存储和处理方面发挥着关键作用。
首先,我们将了解HDFS是如何通过数据分片和数据复制等机制来实现数据的高可靠性存储和容错性。随后,我们将探讨HDFS中节点角色的分工,包括NameNode和DataNode,以及它们是如何协同工作来管理文件系统和存储数据的。接着,我们将讨论HDFS的容错性机制,包括数据复制、健康检查和自动恢复等,以及如何确保系统在面对节点故障或其他异常情况时能够保持正常运行。
HDFS工作原理解析
1. 数据分片(Data Splitting)
HDFS将大文件分割成固定大小的数据块(通常默认为128MB或256MB),并将这些数据块存储在分布式集群中的不同节点上。每个数据块通常在多个节点上复制,以提供容错性和高可用性。
当文件写入HDFS时,HDFS将文件划分为块并负责其复制。此操作(大部分)执行一次,然后可供集群上运行的所有 MR 作业使用。这是集群范围的配置;
数据分片的基本工作原理
-
文件切分:当一个大文件要被存储到HDFS中时,HDFS会将该文件切分成一个个固定大小的数据块。通常情况下,数据块的大小由HDFS的配置决定,默认情况下通常是128MB或256MB。
-
数据块存储:切分后的数据块会被分布式地存储在HDFS集群的不同节点上。这些节点称为DataNode。每个数据块通常会存储在多个DataNode上,以提供数据的冗余备份,以防止数据丢失。
-
数据块的副本:
HDFS会为每个数据块创建多个副本,并将这些副本分布存储在不同的DataNode上。这样做有两个目的:
1.提高数据的可靠性和容错性:当某个DataNode或数据块发生故障时,可以从其他副本中恢复数据。
2.提高数据的读取性能:客户端可以从距离更近的副本读取数据,减少网络传输的开销。 -
数据块的位置信息:NameNode负责维护文件系统的元数据,包括文件和数据块的位置信息。客户端在访问文件时会先与NameNode通信,获取数据块的位置信息,然后直接与相应的DataNode通信进行数据读取或写入操作。
-
数据块的管理:HDFS会定期检查数据块的完整性,并在发现数据块损坏或丢失时进行修复。如果某个数据块的副本数低于指定的阈值,HDFS会自动创建新的副本来替换丢失的副本。
**
2.节点角色
**
在Hadoop分布式文件系统(HDFS)中,有两种主要类型的节点扮演不同的角色:NameNode 和 DataNode。
- HDFS采用master/slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组成。Namenode是一个中心服务器,负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。集群中的Datanode一般是一个节点一个,负责管理它所在节点上的存储。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组Datanode上。Namenode执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体Datanode节点的映射。Datanode负责处理文件系统客户端的读写请求。在Namenode的统一调度下进行数据块的创建、删除和复制。
-
Namenode和Datanode被设计成可以在普通的商用机器上运行。这些机器一般运行着GNU/Linux操作系统(OS)。HDFS采用Java语言开发,因此任何支持Java的机器都可以部署Namenode或Datanode。由于采用了可移植性极强的Java语言,使得HDFS可以部署到多种类型的机器上。一个典型的部署场景是一台机器上只运行一个Namenode实例,而集群中的其它机器分别运行一个Datanode实例。这种架构并不排斥在一台机器上运行多个Datanode,只不过这样的情况比较少见。
集群中单一Namenode的结构大大简化了系统的架构。Namenode是所有HDFS元数据的仲裁者和管理者,这样,用户数据永远不会流过Namenode。
1.NameNode
- NameNode 是HDFS的关键组件之一,负责管理文件系统的命名空间和文件的元数据。
- NameNode 维护了文件系统的目录结构,以及每个文件的元数据信息,如文件名、文件大小、数据块的位置等。
- 当客户端请求读取或写入文件时,NameNode负责确定数据块的位置信息,并将这些信息返回给客户端。
- NameNode是单点故障,因为所有文件系统的元数据都存储在它的内存中。为了防止元数据丢失,通常会定期备份元数据,并启用NameNode的高可用性解决方案,如HA(High Availability)。
2.DataNode:
- DataNode 是HDFS中存储实际数据的节点,它负责存储和检索数据块。
- 当客户端向HDFS写入数据时,DataNode 接收客户端发送的数据块,并将其存储在本地文件系统上。
- 当客户端请求读取文件时,DataNode 负责从本地文件系统读取数据块并将其传输给客户端。
- DataNode 在运行时向NameNode发送心跳消息,用于报告节点的健康状况以及数据块的状态。
3.节点角色工作原理
- 客户端与NameNode通信,获取文件的元数据信息。
- NameNode 返回文件的元数据信息给客户端。
- 客户端根据元数据信息直接与DataNode通信,进行数据读取或写入操作。
- DataNode 在写入或读取数据时,负责与客户端进行实际的数据传输。
**
3.数据访问
**
数据访问是指客户端从HDFS中读取数据或向HDFS中写入数据的过程。以下是数据访问的基本工作原理:
1.读取数据的工作原理
- 客户端首先与NameNode通信,请求读取特定文件的数据。客户端提供文件路径等信息给NameNode。
- NameNode返回包含文件的元数据信息,包括文件的大小、数据块的位置等。
- 客户端根据元数据信息确定数据块的位置,并向对应的DataNode发送读取请求。
- DataNode接收到读取请求后,从本地存储中读取数据块,并将数据返回给客户端。
2.写入数据的工作原理
- 客户端首先与NameNode通信,请求将数据写入到指定的文件中。客户端提供文件路径等信息给NameNode。
- NameNode确定数据写入的位置以及数据块的分配情况,并将这些信息返回给客户端。
- 客户端将数据按照数据块进行分割,并将每个数据块发送给对应的DataNode。
- DataNode接收到数据块后,负责存储数据,并向客户端发送确认信息,表示数据写入操作完成。
3.数据块的复制与容错处理
- 在数据写入过程中,HDFS会根据副本配置策略,在集群中的其他DataNode上创建相应数量的数据块副本。这些副本的创建是异步进行的,并且在后台由HDFS系统自动管理。
- 当某个DataNode或数据块发生故障时,HDFS能够自动检测到故障并进行处理。如果某个数据块的副本数低于指定的阈值,HDFS会自动创建新的副本来替换丢失的副本。
步骤1:客户端通过调用文件系统对象(对于HDFS来说是分布式文件系统的一个实例)上的open()来打开它希望读取的文件。
步骤 2:分布式文件系统 (DFS) 使用远程过程调用 (RPC) 调用名称节点,以确定文件中前几个块的位置。对于每个块,名称节点返回具有该块副本的数据节点的地址。 DFS 将 FSDataInputStream 返回给客户端以供其读取数据。 FSDataInputStream 又包装了一个 DFSInputStream,它管理数据节点和名称节点 I/O。
步骤 3:然后客户端在流上调用 read()。 DFSInputStream 存储了文件中主要几个块的信息节点地址,然后连接到文件中主要块的主要(最近)数据节点。
步骤 4:数据从数据节点流式传输回客户端,客户端在流上重复调用 read()。
步骤5:当到达块的末尾时,DFSInputStream将关闭与数据节点的连接,然后为下一个块寻找最佳数据节点。这对客户端来说是透明的,从客户端的角度来看,这只是在读取无尽的流。块被读取为,DFSInputStream 打开到数据节点的新连接,因为客户端读取流。它还将根据需要调用名称节点来检索下一批块的数据节点位置。
第 6 步:当客户端完成读取文件后,将调用 FSDataInputStream 上的 close() 函数。
**
4.数据复制
**
数据复制是指在HDFS中将数据块复制到多个节点以增加数据的容错性和可用性。
- HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件存储成一系列的数据块,除了最后一个,所有的数据块都是同样大小的。为了容错,文件的所有数据块都会有副本。每个文件的数据块大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。HDFS中的文件都是一次性写入的,并且严格要求在任何时候只能有一个写入者。
Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表。
副本存放: 最最开始的一步
- 副本的存放是HDFS可靠性和性能的关键。优化的副本存放策略是HDFS区分于其他大部分分布式文件系统的重要特性。这种特性需要做大量的调优,并需要经验的积累。HDFS采用一种称为机架感知(rack-aware)的策略来改进数据的可靠性、可用性和网络带宽的利用率。目前实现的副本存放策略只是在这个方向上的第一步。实现这个策略的短期目标是验证它在生产环境下的有效性,观察它的行为,为实现更先进的策略打下测试和研究的基础。大型HDFS实例一般运行在跨越多个机架的计算机组成的集群上,不同机架上的两台机器之间的通讯需要经过交换机。在大多数情况下,同一个机架内的两台机器间的带宽会比不同机架的两台机器间的带宽大。通过一个机架感知的过程,Namenode可以确定每个Datanode所属的机架id。一个简单但没有优化的策略就是将副本存放在不同的机架上。这样可以有效防止当整个机架失效时数据的丢失,并且允许读数据的时候充分利用多个机架的带宽。这种策略设置可以将副本均匀分布在集群中,有利于当组件失效情况下的负载均衡。但是,因为这种策略的一个写操作需要传输数据块到多个机架,这增加了写的代价。在大多数情况下,副本系数是3,HDFS的存放策略是将一个副本存放在本地机架的节点上,一个副本放在同一机架的另一个节点上,最后一个副本放在不同机架的节点上。这种策略减少了机架间的数据传输,这就提高了写操作的效率。机架的错误远远比节点的错误少,所以这个策略不会影响到数据的可靠性和可用性。于此同时,因为数据块只放在两个(不是三个)不同的机架上,所以此策略减少了读取数据时需要的网络传输总带宽。在这种策略下,副本并不是均匀分布在不同的机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,其他副本均匀分布在剩下的机架中,这一策略在不损害数据可靠性和读取性能的情况下改进了写的性能。
数据复制的基本工作原理:
-
副本配置:
HDFS的副本配置是通过参数设置的,通常在Hadoop集群的配置文件中指定。这些参数包括每个数据块的副本数目以及副本放置策略。 -
副本创建:
当客户端向HDFS写入数据时,根据副本配置,HDFS会在写入数据块时为每个数据块创建指定数量的副本。这些副本通常存储在集群中的不同节点上。 -
副本放置:
1.HDFS会根据副本放置策略,将数据块的副本分布在集群的不同节点上。默认情况下,HDFS会尽量将副本分布在不同的机架上,以降低机架级别的故障对数据的影响。
2.如果集群中有多个机架,则HDFS会将数据块的副本均匀分布在这些机架上。这样做可以提高数据的容错性,以防止机架级别的故障导致数据不可用。 -
副本管理:
1.HDFS会定期检查数据块的副本情况,并根据需要创建新的副本或删除多余的副本。如果某个副本因节点故障或其他原因不可用,HDFS会自动将其替换为新的副本,以保证数据的可靠性和可用性。
2.当客户端向HDFS写入数据时,如果数据块的副本数低于指定的阈值,HDFS会立即创建新的副本,以确保数据的容错性。 -
副本同步
当数据块的主副本更新时,HDFS会通过后台线程将这些更新同步到其他副本上。这样可以确保所有副本的数据保持一致性。
**
5.容错性
**
容错性是指系统在面对硬件故障、软件错误或其他异常情况时能够保持正常运行的能力。容错性是通过以下几种机制来实现的:
数据复制
- HDFS将数据切分为固定大小的数据块,并在集群中多个节点上存储数据块的副本。当某个节点或数据块发生故障时,HDFS能够从其他副本中恢复数据,确保数据的可靠性和可用性。
- 创建的副本数量取决于复制因子,默认情况下为3。如果任何计算机出现故障,则可以从包含相同数据副本的另一台计算机访问该数据块。因此,不会因为副本存储在不同的机器上而导致数据丢失。
HDFS复制机制示例
假设用户存储一个文件。 HDFS 将这个文件分成块;说 B1、B2、B3、B4 和 B5。假设有五个数据节点,即 D1、D2、D3、D4 和 D5。 HDFS为每个块创建副本并将其存储在不同的节点上以实现容错。对于每个原始块,将在不同节点上存储三个副本(复制因子3)。让块1存储在数据节点D1、D2和D3上,块2存储在数据节点D1、D4和D5上,其他3个块类似。如果数据节点 1 发生故障,则用户仍可从数据节点(B1 为 D2、D3)、B2(B2 为 D4、D5)和(B4 为 D2、D5)使用 D1 中存在的块 1、2 和 4。因此,即使在不利的条件下,也不会丢失数据。
健康检查和心跳机制
- DataNode定期向NameNode发送心跳消息,报告节点的健康状况以及数据块的状态。如果NameNode在一定时间内未收到某个DataNode的心跳消息,则会将该节点标记为不可用,并将其上的数据块副本复制到其他节点上,以确保数据的容错性。
故障检测和自动恢复
- HDFS能够自动检测到节点或数据块的故障,并在必要时进行故障处理和数据恢复。当某个数据块的副本数低于指定的阈值时,HDFS会自动创建新的副本以保证数据的完整性。
高可用性解决方案
- HDFS提供了一些高可用性解决方案,如NameNode的HA(HighAvailability),通过在集群中运行多个NameNode实例,并使用共享存储或共享编辑日志来实现故障切换,以提高NameNode的可用性。
数据校验
- HDFS在存储数据时会使用数据校验和(checksum)来验证数据的完整性。当数据被读取时,HDFS会校验数据的完整性,以检测数据的损坏或篡改,并在必要时重新获取数据块的副本。
**
6.数据写入流程
**
数据写入流程是指将数据写入到HDFS中的过程,包括客户端向HDFS写入数据的整个流程。以下是数据写入流程的基本工作原理:
客户端请求:
- 客户端向HDFS发送写入请求,请求将数据写入到指定的文件中。
NameNode操作:
- 客户端与NameNode通信,请求向文件中写入数据。NameNode负责管理文件系统的元数据,包括文件的命名空间、文件和数据块的位置信息等。
数据块分配:
- NameNode确定数据写入的文件位置以及数据块的分配情况。它会告知客户端应该将数据写入到哪些数据块中,以及这些数据块在集群中的位置。
数据写入:
- 客户端按照NameNode返回的信息,将数据按照数据块进行分割,并通过网络发送给集群中的DataNode。
- 客户端与DataNode进行直接通信,将数据写入到指定的数据块中。数据写入过程中,DataNode负责存储数据并确认写入操作的完成。
数据复制
- 当数据写入完成后,HDFS会根据副本配置策略,在集群中的其他DataNode上创建相应数量的数据块副本。这些副本的创建是异步进行的,并且在后台由HDFS系统自动管理。
确认写入
- DataNode在完成数据写入操作后向客户端发送确认信息,告知客户端数据写入操作的状态。客户端收到确认信息后,可以继续执行后续操作。
元数据更新
- 在数据写入操作完成后,NameNode会更新文件系统的元数据,包括文件的大小、数据块的位置信息等。这样可以确保文件系统的元数据与实际数据存储的一致性。
总的来说,数据写入流程是客户端与NameNode和DataNode之间进行交互的过程,考虑配图以更好地理解这个概念
步骤1:客户端通过调用DistributedFileSystem(DFS)上的create()来创建文件。
第 2 步: DFS 对名称节点进行 RPC 调用,以在文件系统的命名空间中创建一个新文件,并且没有与其关联的块。名称节点执行各种检查以确保该文件尚不存在并且客户端具有创建该文件的正确权限。如果这些检查通过,名称节点会准备新文件的记录;否则,无法创建该文件,因此客户端会抛出错误,即 IOException。 DFS 返回一个 FSDataOutputStream 供客户端开始写入数据。
步骤 3:由于客户端写入数据,DFSOutputStream 将其拆分为数据包,并将其写入称为信息队列的室内队列。数据队列由 DataStreamer 消耗,DataStreamer 负责要求名称节点通过选择合适的数据节点清单来存储副本来分配新块。数据节点列表形成一个管道,这里我们假设复制级别为三,因此管道中有三个节点。 DataStreamer 将数据包流式传输到管道内的主数据节点,该节点存储每个数据包并将其转发到管道内的第二数据节点。
步骤 4:类似地,第二个数据节点存储数据包并将其转发到管道中的第三个(也是最后一个)数据节点。
步骤 5: DFSOutputStream 维护等待数据节点确认的数据包的内部队列,称为“ack 队列”。
步骤 6:此操作将所有剩余数据包发送到数据节点管道,并在连接到名称节点以指示文件是否完整之前等待确认。