目录
[一、Hadoop 基础概念](#一、Hadoop 基础概念)
[二、Hadoop 运行模式](#二、Hadoop 运行模式)
[3.1 HDFS 架构与组件](#3.1 HDFS 架构与组件)
[3.2 HDFS 读写流程](#3.2 HDFS 读写流程)
[3.3 HDFS 容错机制](#3.3 HDFS 容错机制)
[4.1 MapReduce 原理与架构](#4.1 MapReduce 原理与架构)
[4.2 MapReduce 任务执行流程](#4.2 MapReduce 任务执行流程)
[4.3 Combiner 和 Shuffle 机制](#4.3 Combiner 和 Shuffle 机制)
[5.1 YARN 架构与组件](#5.1 YARN 架构与组件)
[5.2 YARN 资源调度](#5.2 YARN 资源调度)
[5.3 YARN 应用提交与运行](#5.3 YARN 应用提交与运行)
一、Hadoop 基础概念
Hadoop 是一个开源的分布式计算平台,能够使用简单的编程模型跨计算机集群分布式处理大规模数据,为任何类型的数据提供海量存储,巨大的处理能力以及处理几乎无限的并发任务或作业的能力。它的核心组件包括 HDFS(Hadoop Distributed File System)、MapReduce 和 Yarn,这些组件相互协作,使得 Hadoop 能够高效地处理和存储海量数据。
HDFS 是 Hadoop 的分布式文件系统,主要用于解决海量数据的存储问题。它具有高容错性,能检测和应对硬件故障,适合部署在廉价的机器上,通过多副本机制,提高可靠性。在 HDFS 中,文件被切分成一个个 Block 存储,默认块大小在 Hadoop2.x 版本中是 128MB,每个 Block 可以设置副本数,默认是 3,且副本会存储在不同服务器上,以保证数据的可用及容错。HDFS 采用主从结构,NameNode 作为主节点,负责管理文件命名空间和调节客户端访问文件,维护整个 HDFS 的目录树以及文件对应的 Block 信息;DataNode 作为从节点,负责管理对应节点的存储,执行来自文件系统客户的读写请求,以及块的创建、删除和复制指令。
MapReduce 是一种分布式计算模型,用于处理大规模数据的并行计算,其核心思想是将数据处理过程分为 Map 和 Reduce 两个阶段。在 Map 阶段,Map 函数对数据集上的独立元素进行指定操作,生成键值对形式的中间结果;在 Reduce 阶段,Reduce 函数对中间结果中相同键的所有值进行规约,以得到最终结果。例如在 WordCount 示例中,Map 函数将文本中的每个单词作为键,值设为 1 输出;Reduce 函数则将相同单词的计数值累加,得到每个单词在文本中出现的总次数。MapReduce 具有易于编程、良好扩展性、高容错性等优点,适合 PB 级以上海量数据的离线处理,但它不擅长实时计算、流式计算和 DAG 计算。
Yarn 是 Hadoop 的资源管理和任务调度框架,是一种新的 Hadoop 资源管理器,为上层应用提供统一的资源管理和调度。它的基本思想是将 JobTracker 的资源管理和作业调度 / 监控功能分离,创建一个全局的 ResourceManager 和若干个针对应用程序的 ApplicationMaster。ResourceManager 负责整个系统的资源管理和分配,调度器根据容量、队列等限制条件将资源分配给各个应用程序;ApplicationMaster 负责管理一个应用程序的每个实例,协调来自 ResourceManager 的资源,并监视容器的执行和资源使用。NodeManager 则管理集群中的每个节点,提供针对每个节点的服务,包括监督容器的终生管理、监视资源和跟踪节点健康等。Yarn 的出现大大减少了 JobTracker 的资源消耗,让监测 Job 子任务状态的程序分布式化,提高了系统的安全性和优美性,同时使得 Hadoop 可以支持更多类型的编程模型。
二、Hadoop 运行模式
Hadoop 有三种运行模式,分别是单机模式、伪分布式模式和完全分布式模式,不同模式适用于不同的场景,了解它们的特点和应用场景有助于在实际应用中做出正确选择。
单机模式:单机模式是 Hadoop 最基础的运行模式,也称为本地模式。在这种模式下,Hadoop 的所有组件都运行在同一台机器上,没有分布式文件系统 HDFS,而是直接读写本地操作系统的文件系统,所有程序都在同一个 JVM 上执行,无需启动任何守护进程。单机模式主要用于开发和调试阶段,比如在编写和测试 MapReduce 程序时,开发人员可以利用单机模式快速验证程序逻辑是否正确,由于不需要搭建复杂的分布式环境,能够节省大量时间和资源。像在学习 Hadoop 编程的初期,通过单机模式运行简单的 WordCount 示例程序,能帮助初学者快速上手,熟悉 MapReduce 的基本流程。
伪分布式模式:伪分布式模式同样运行在单台机器上,但与单机模式不同,它利用多个 Java 进程来模拟分布式环境中各类节点,包括 NameNode、DataNode、ResourceManager、NodeManager 等,具备 Hadoop 的主要功能,使用 HDFS 作为存储系统。这种模式可以模拟数据分片和分布式计算的过程,使开发人员能在本地环境中更真实地了解 Hadoop 的工作原理,常用于程序的调试和测试。例如,开发人员在进行一些较为复杂的数据分析程序开发时,先在伪分布式模式下进行调试,能够提前发现程序在分布式环境下可能出现的问题,如数据读取、任务分配等方面的错误。不过,伪分布式模式由于所有组件都在同一台机器上运行,当这台机器出现故障时,数据就会丢失,而且无法提供真正的分布式性能和容错能力。
完全分布式模式:完全分布式模式是 Hadoop 用于生产环境的运行模式,在这种模式下,Hadoop 集群由多台机器组成,每个节点都扮演着不同的角色,有一个 NameNode 和多个 DataNode,以及一个 ResourceManager 和多个 NodeManager。NameNode 负责管理文件系统的命名空间和客户端对文件的访问,DataNode 负责存储实际的数据块;ResourceManager 负责整个集群的资源管理和调度,NodeManager 负责管理每个节点上的资源和任务。完全分布式模式通过分布式存储和计算的方式,能够处理大规模的数据集,并且利用副本机制保证当其中一个 DataNode 节点故障时数据还能正常访问,同时通过 SecondaryNameNode 和高可用机制,保证整个集群不间断地提供服务,具有高可靠性和高容错性。像互联网公司处理海量的用户日志数据、电商平台分析大规模的交易数据时,就会采用完全分布式模式的 Hadoop 集群,以满足对大数据处理的性能和可靠性要求。
三、HDFS
3.1 HDFS 架构与组件
HDFS 采用主从(Master/Slave)架构,一个 HDFS 集群通常由一个 NameNode 和多个 DataNode 组成,在某些情况下还会包含一个 SecondaryNameNode。
NameNode:NameNode 是 HDFS 的核心组件,作为 Master 节点,起着主管和管理者的作用,类似于一个公司的 CEO,负责宏观决策和资源分配。它主要管理 HDFS 的名称空间,就像一个图书馆的管理员,负责维护书籍(文件)的目录结构,让用户能够通过文件名准确找到对应的文件。同时,NameNode 配置副本策略,决定数据块在 DataNode 上的副本数量和分布,以确保数据的可靠性和容错性,比如默认会将每个数据块复制成 3 个副本存储在不同的 DataNode 上。它还管理数据块(Block)映射信息,记录每个文件由哪些数据块组成,以及这些数据块存储在哪些 DataNode 上,方便快速定位数据。当客户端发起读写请求时,NameNode 会处理这些请求,就像公司的 CEO 接收和处理重要事务一样。NameNode 将文件系统的元数据存储在内存中,包括文件和目录的元数据信息,同时在磁盘上保存编辑日志(EditLog)和命名空间镜像(FsImage),EditLog 记录了所有对文件系统元数据的更改操作,FsImage 则是文件系统元数据在某个时间点的快照。当 NameNode 启动时,会将 FsImage 加载到内存,并根据 EditLog 中的记录对元数据进行恢复和更新,以保证内存中的元数据是最新且一致的。
DataNode:DataNode 是 HDFS 的从节点,相当于公司里的基层员工,负责执行实际的操作。它在本地文件系统存储文件块数据,以及块数据的校验和,就像仓库中的货架,实实在在地存放着货物(数据)。DataNode 会根据 NameNode 的命令执行数据块的读 / 写操作,当客户端请求读取数据时,DataNode 会从本地磁盘读取相应的数据块并返回给客户端;当客户端请求写入数据时,DataNode 会接收数据并存储到本地磁盘。DataNode 定期向 NameNode 上报心跳信息,告知 NameNode 自己的健康状态,就像员工定期向领导汇报工作进展一样,默认每 3 秒发送一次心跳。同时,DataNode 还会周期性(默认 6 小时)地向 NameNode 上报所有的块信息,以便 NameNode 了解整个集群的数据分布情况。如果 NameNode 在 10 分钟 + 30 秒内没有收到某个 DataNode 的心跳,则认为该 DataNode 不可用,会采取相应的措施,如重新复制该 DataNode 上的数据块到其他可用的 DataNode,以保证数据的可用性。
SecondaryNameNode:SecondaryNameNode 并非 NameNode 的热备,当 NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。它更像是 NameNode 的助手,主要作用是分担 NameNode 的工作量。由于 NameNode 的 EditLog 会不断增长,长时间不处理会导致文件过大,影响系统性能,SecondaryNameNode 会定期(默认 1 小时)从 NameNode 获取 EditLog 和 FsImage,将它们合并成一个新的 FsImage,然后将新的 FsImage 传回给 NameNode,这个过程就像是定期对图书馆的目录进行整理和更新。通过这种方式,SecondaryNameNode 帮助 NameNode 清理 EditLog,防止 NameNode 的内存溢出,提高系统的稳定性和性能。在紧急情况下,比如 NameNode 的元数据损坏,SecondaryNameNode 可以辅助恢复 NameNode 的元数据,通过将自己合并生成的新 FsImage 拷贝到 NameNode,帮助 NameNode 恢复到一个相对完整的状态。
3.2 HDFS 读写流程
HDFS 的读写流程涉及客户端与 NameNode、DataNode 之间的复杂交互,确保数据能够高效、可靠地存储和读取。
写数据流程:当客户端想要上传一个文件到 HDFS 时,首先通过 DistributedFileSystem API 向 NameNode 发出文件写入请求。NameNode 检查文件是否已存在以及目标目录的权限,如果文件不存在且客户端有写入权限,NameNode 会创建新文件的记录,并返回给客户端一个唯一的文件标识符以及数据块的存储策略。接着,客户端请求第一个数据块的存储位置,NameNode 根据数据块的复制策略(默认为 3 副本),考虑机架感知策略选择合适的 DataNode,以确保数据的可靠性和容错性,并将这些 DataNode 的位置信息返回给客户端。客户端按照 NameNode 返回的 DataNode 列表的顺序,建立一个数据写入的 pipeline。客户端首先将数据写入第一个 DataNode(DN1),DN1 收到数据后,立即转发给第二个 DataNode(DN2),DN2 再转发给第三个 DataNode(DN3),形成一个数据流动的管道,每个 DN 节点在接收到数据后都会进行校验并存储。客户端将数据切分成多个 Packet(数据包)进行传输,每个 Packet 在 pipeline 中流动时,DN 节点会向客户端发送 ACK 确认信息,客户端收到所有 DN 的 ACK 后,才会继续发送下一个 Packet。当所有数据块都按照这种方式写入完成后,客户端向 NameNode 报告写入完成,NameNode 更新元数据,标记文件写入结束。
读数据流程:客户端通过 Distributed FileSystem API 向 NameNode 发起读取文件的请求,提供文件路径。NameNode 根据文件路径查找元数据,验证文件是否存在及客户端是否有权限读取,并返回该文件所有数据块的位置信息。客户端根据 DataNode 列表选择最近或最合适的 DataNode 开始读取数据块,优先选择距离客户端近的节点,以减少网络传输开销,提高读取效率。客户端直接与 DataNode 建立连接,逐个读取数据块。如果数据块的副本分布在不同的节点上,客户端可以根据网络状况选择最优的副本进行读取,以优化读取性能。对于大文件,客户端可能需要从多个 DataNode 读取不同的数据块,并在客户端侧将这些数据块合并,以还原完整的文件内容。一旦所有数据块都被成功读取,客户端完成文件读取操作。
3.3 HDFS 容错机制
HDFS 通过多种机制实现容错,确保数据的可靠性和集群的稳定性。
数据复制:HDFS 将文件划分为固定大小的块,并将每个块复制到多个节点上,默认情况下,每个块会复制到集群中的三个不同的节点上。这种数据冗余的方式可以有效防止数据丢失,当某个节点出现故障时,其他节点上的副本仍然可用。例如,当一个 DataNode 宕机时,NameNode 可以从其他拥有该数据块副本的 DataNode 获取数据,保证数据的正常读取和使用。
副本放置策略:为了进一步提高数据的容错性,HDFS 采用了智能的副本放置策略。在经典的三副本情况下,第一个副本放在发起写请求的客户端上(如果客户端不在 DataNode 上,那么随机选取一个同 rack 的 Datanode 存放);第二个副本放在与第一个副本所在 DataNode 不同 rack 的 DataNode 上,这样可以防止整个机架出现故障时数据丢失;第三个副本放在与第二个副本所在 DataNode 的相同 rack 的不同 DataNode 上。通过这种策略,HDFS 可以在不同的故障场景下保证数据的可用性。
心跳机制和故障检测:HDFS 使用心跳机制来定期检测集群中的节点是否处于正常工作状态。DataNode 会定期向 NameNode 发送心跳信号,如果 NameNode 在规定时间内没有接收到某个 DataNode 的心跳,就会认定该 DataNode 发生了故障。同时,DataNode 还会定期发送块报告给 NameNode,列出它存储的所有数据块。如果 NameNode 没有收到某个 DataNode 的块报告,也会进一步确认该 DataNode 是否故障。一旦检测到 DataNode 故障,NameNode 会采取相应的措施,如重新复制该 DataNode 上的数据块到其他可用的 DataNode,以确保数据的完整性。
自动故障恢复:当一个数据块的副本丢失或变得不可用时,HDFS 会自动从其他可用的副本中选择一个进行复制,以确保每个数据块都有足够的副本数。例如,当某个 DataNode 上的数据块损坏或丢失时,NameNode 会通知其他拥有该数据块副本的 DataNode,将副本复制到新的节点上,从而恢复数据的完整性。此外,HDFS 还支持数据校验和,在读取数据时,会对数据进行校验,确保数据的正确性,如果发现数据错误,会从其他副本中读取正确的数据。在 NameNode 或 DataNode 挂掉时,HDFS 也有相应的应对措施。对于 NameNode,在 Hadoop 2.x 之前,一个集群只有一个 NameNode,存在单点故障问题。在 Hadoop 2.0 之后,引入了 NameNode 高可用(HA)机制,通过配置两个 NameNode,一个处于活动状态(Active),负责处理集群中所有客户端请求;另一个处于备用状态(Standby),拥有和活动 NameNode 一样的元数据。当活动 NameNode 失效后,备用 NameNode 会自动接管它的工作,实现自动故障切换,保证集群的正常运行。对于 DataNode,当 DataNode 宕机时,NameNode 会检测到故障,并将该 DataNode 上的数据块复制到其他健康的 DataNode 上,以保证数据的可用性。同时,当 DataNode 恢复正常后,它会重新向 NameNode 注册,并根据 NameNode 的指示进行数据同步和修复。
四、MapReduce
4.1 MapReduce 原理与架构
MapReduce 是一种分布式计算模型,用于大规模数据集的并行处理,核心思想是"分而治之"。它将数据处理过程分为 Map 和 Reduce 两个阶段,借鉴了函数式语言中的思想,用 Map 和 Reduce 两个函数提供了高层的并行编程抽象模型。
在 Map 阶段,Map 函数会对输入数据集中的每个元素进行处理,将其转换为键值对形式的中间结果。比如在处理一篇文档时,Map 函数会将文档中的每一行拆分成单词,并以单词为键,出现次数 1 为值,输出一系列键值对,就像从一堆杂乱的物品中,把相同类型的物品先挑出来并做个标记。每个 Map 任务会处理一部分输入数据,这些任务可以在不同的节点上并行执行,大大提高了处理效率。例如在一个包含 1000 篇文档的数据集上进行单词统计,可能会启动多个 Map 任务,每个任务处理 100 篇文档,它们同时工作,快速完成初步的单词提取和计数。
Reduce 阶段则会对 Map 阶段输出的具有相同键的中间结果进行汇总和处理。接着上面的例子,Reduce 函数会把所有以相同单词为键的键值对收集起来,将这些键值对中的值进行累加,得到每个单词在整个数据集中出现的总次数。Reduce 任务同样可以并行执行,每个 Reduce 任务处理一部分键值对。例如,可能有多个 Reduce 任务同时工作,分别处理不同字母开头的单词的统计结果。
在 MapReduce 架构中,主要涉及 Client、JobTracker、TaskTracker 和 Task 这几个组件。Client 是用户提交 MapReduce 作业的客户端,用户编写好 MapReduce 程序后,通过 Client 将作业提交到 JobTracker 端,就像员工向领导提交工作任务。Client 还可以查看作业的运行状态,随时了解任务的进展情况。JobTracker 是 MapReduce 的核心组件之一,相当于一个项目的总负责人,负责资源监控和作业调度。它监控所有 TaskTracker 与 Job 的健康状况,一旦发现某个 TaskTracker 或 Job 出现问题,比如某个节点死机或者某个任务长时间无响应,就会将相应的任务转移到其他节点,保证整个作业能够顺利进行。JobTracker 还会跟踪任务的执行进度、资源使用量等信息,并将这些信息告诉任务调度器,由调度器在资源出现空闲时,选择合适的任务去使用这些资源,合理分配工作任务,提高工作效率。TaskTracker 负责执行具体的任务,运行在集群中的每个节点上,它就像项目中的执行者,从 JobTracker 接收任务并执行。TaskTracker 会周期性地通过"心跳"将本节点上资源的使用情况和任务的运行进度汇报给 JobTracker,就像员工定期向领导汇报工作情况。同时,TaskTracker 使用"slot"等量划分本节点上的资源量,一个 Task 获取到一个 slot 后才有机会运行,比如一个节点有 8 个 CPU 核心,可能会划分为 8 个 slot,每个任务运行时需要占用一个或多个 slot。Task 分为 Map Task 和 Reduce Task 两种,均由 TaskTracker 启动,分别负责 Map 阶段和 Reduce 阶段的数据处理流程。
4.2 MapReduce 任务执行流程
作业提交:用户编写好 MapReduce 程序后,通过 Client 提交作业。Client 首先会对作业进行检查,比如检查输入输出路径是否正确、Map 和 Reduce 函数是否实现等。然后,Client 会计算作业的输入分片(InputSplit),将输入数据划分为多个逻辑分片,每个分片对应一个 Map 任务。Client 会将作业相关的资源,如程序代码、配置文件等,上传到 HDFS 的指定目录,并向 JobTracker 提交作业请求。
作业初始化:JobTracker 接收到作业请求后,会为作业分配一个唯一的 JobID,并创建一个 JobInProgress 对象来管理该作业。JobTracker 会检查作业的依赖关系,比如是否需要其他的文件或库。JobTracker 会根据作业的输入分片信息,为每个分片创建一个 Map 任务,并根据用户设置的 Reduce 任务数量创建相应的 Reduce 任务。JobTracker 会将这些任务分配到集群中的 TaskTracker 上执行。
Map 任务执行:每个 TaskTracker 在接收到 Map 任务后,会启动一个 MapTask 进程来执行任务。MapTask 首先会从 HDFS 中读取对应的输入分片数据。然后,MapTask 会调用用户定义的 Map 函数,对输入数据进行处理,将其转换为键值对形式的中间结果。例如在 WordCount 程序中,Map 函数会将文本中的每个单词作为键,值设为 1 输出。MapTask 会将这些中间结果写入到内存中的环形缓冲区(默认大小为 100MB)。当缓冲区的数据量达到阈值(默认是 80%)时,会启动一个溢写线程,将缓冲区的数据溢写到磁盘上的临时文件中。在溢写过程中,会对数据进行分区、排序和合并操作。分区是根据键的哈希值将数据分配到不同的分区,每个分区对应一个 Reduce 任务 ;排序是按照键的字典序对数据进行排序 ;合并是将相同键的值进行合并,减少数据量。当 Map 任务处理完所有输入数据后,会将磁盘上的所有临时文件合并成一个最终的输出文件。
Shuffle 过程:Shuffle 过程是 MapReduce 的核心,它负责将 Map 任务的输出数据传输到 Reduce 任务。在 Map 任务完成后,Reduce 任务会通过 HTTP 协议从 Map 任务所在的节点拉取属于自己分区的数据。在拉取数据的过程中,会对数据进行进一步的排序和合并操作。Reduce 任务会将拉取到的数据按照键进行分组,将相同键的值放在一起,形成一个键值对列表,为后续的 Reduce 阶段做准备。
Reduce 任务执行:每个 TaskTracker 在接收到 Reduce 任务后,会启动一个 ReduceTask 进程来执行任务。ReduceTask 会读取 Shuffle 阶段生成的键值对列表,并调用用户定义的 Reduce 函数,对相同键的值进行汇总和处理。在 WordCount 程序中,Reduce 函数会将相同单词的计数值累加,得到每个单词在文本中出现的总次数。ReduceTask 会将处理后的结果写入到 HDFS 中指定的输出路径。
作业完成:当所有的 Map 任务和 Reduce 任务都执行完成后,JobTracker 会将作业状态设置为"完成",并通知 Client。Client 可以通过命令行或其他方式查看作业的执行结果。
4.3 Combiner 和 Shuffle 机制
Combiner 是 MapReduce 中的一个可选组件,它的作用类似于局部的 Reducer。Combiner 主要用于在 Map 阶段对输出结果进行局部汇总,以减少 Shuffle 过程中传输的数据量,从而降低网络传输的开销,并且减轻 Reduce 任务的负载,提高整个 MapReduce 作业的性能。例如在 WordCount 示例中,如果没有 Combiner,每个 Map 任务输出的大量单词计数键值对都要完整地传输到 Reduce 阶段。而有了 Combiner 后,它会在 Map 任务本地先对相同单词的计数进行合并。比如一个 Map 任务处理的文本中"apple"出现了 10 次,经过 Combiner 处理,就会将这 10 个计数合并成一个键值对("apple", 10),然后再传输到 Reduce 阶段,大大减少了传输的数据量。
Combiner 的使用场景通常是在一些满足可交换和可结合性质的操作中。比如求和、计数、最大值、最小值等操作。以求和操作为例,无论是先在 Map 端局部求和再在 Reduce 端汇总,还是直接在 Reduce 端对所有值求和,结果都是一样的。但对于一些不满足可交换和可结合性质的操作,如求平均数,就不适合使用 Combiner。因为如果先在 Map 端对部分数据求平均数,再在 Reduce 端对这些平均数求平均数,得到的结果与直接对所有数据求平均数的结果是不同的。
Shuffle 机制则是 MapReduce 的核心,它描述了数据从 Map 阶段流入 Reduce 阶段的过程,这个过程涉及到数据的分区、排序、合并和传输等多个操作。在 Map 阶段,Map 任务处理完数据后,会将中间结果写入到内存中的环形缓冲区。当缓冲区的数据量达到阈值时,会启动溢写线程,将缓冲区的数据溢写到磁盘上的临时文件中。在溢写之前,会对数据进行分区操作。分区是根据键的哈希值将数据分配到不同的分区,每个分区对应一个 Reduce 任务,这样可以确保相同键的数据最终会被发送到同一个 Reduce 任务进行处理。例如在处理一个包含用户购买记录的数据集时,可以按照用户 ID 进行分区,使得同一个用户的所有购买记录都能在同一个 Reduce 任务中进行汇总分析。同时,在溢写过程中,还会对数据按照键进行排序,默认是按照字典序排序,排序可以让相同键的数据相邻,方便后续的合并和处理。如果用户设置了 Combiner,还会对相同键的数据进行合并操作,减少数据量。当 Map 任务完成后,会将磁盘上的所有临时文件合并成一个最终的输出文件。在 Reduce 阶段,Reduce 任务会通过 HTTP 协议从 Map 任务所在的节点拉取属于自己分区的数据。在拉取数据的过程中,会对数据进行进一步的排序和合并操作,将从多个 Map 任务拉取到的相同分区的数据合并成一个大文件。然后,Reduce 任务会将合并后的文件按照键进行分组,将相同键的值放在一起,形成一个键值对列表,最后调用 Reduce 函数对这些键值对进行处理。
五、YARN
5.1 YARN 架构与组件
YARN(Yet Another Resource Negotiator)是 Hadoop 的资源管理和任务调度框架,为上层应用提供统一的资源管理和调度,它的出现使得 Hadoop 能够更好地支持多种计算框架,提高集群资源利用率。YARN 主要由 ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)和 Container 等组件构成。
ResourceManager 是整个集群的核心,负责集群资源的统一管理和调度,就像一个公司的总经理,掌控着公司的所有资源分配。它处理来自客户端的请求,比如接收用户提交的作业请求 ;监控 NodeManager,确保各个节点正常运行,定期检查各个节点的健康状况 ;启动或监控 ApplicationMaster,当某个 ApplicationMaster 出现故障时,及时重新启动它 ;进行资源的分配与调度,根据各个应用程序的需求,合理分配内存、CPU 等资源。
NodeManager 是 YARN 在每个节点上的代理,负责管理单个节点上的资源,类似于公司里各个部门的主管,管理本部门的资源和工作任务。它处理来自 ResourceManager 的命令,如启动或停止容器 ;处理来自 ApplicationMaster 的命令,按照 ApplicationMaster 的要求执行具体的任务 ;定期向 ResourceManager 汇报本节点上的资源使用情况,包括 CPU 使用率、内存使用量等,以及各个 Container 的运行状态,让 ResourceManager 随时了解集群中每个节点的资源使用情况。
ApplicationMaster 是每个应用程序特有的,负责应用程序的管理,就像每个项目的项目经理,负责项目的具体实施和管理。它为应用程序向 ResourceManager 申请资源,根据应用程序的需求,向 ResourceManager 请求一定数量的 Container ;将获得的资源分配给内部的任务,合理安排每个任务使用哪些资源 ;与 NodeManager 通信以启动、停止任务,确保任务能够在指定的节点上顺利运行 ;监控所有任务运行状态,一旦某个任务出现故障,及时为该任务申请资源以重启任务,保证应用程序的正常执行。
Container 是 YARN 中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,是任务运行的载体,类似于一个工作间,里面配备了完成任务所需的各种资源。Container 由 AM 向 RM 申请,RM 根据资源情况和调度策略将 Container 分配给 AM,然后 AM 与资源所在的 NM 通信,启动 Container。一个应用程序可能会使用多个 Container,这些 Container 分布在不同的节点上,共同完成应用程序的任务。
5.2 YARN 资源调度
YARN 的资源调度是其核心功能之一,通过合理的调度策略,能够充分利用集群资源,提高作业的执行效率。YARN 默认提供了三种资源调度器:FIFO Scheduler、Capacity Scheduler 和 Fair Scheduler,每种调度器都有其特点和适用场景。
FIFO Scheduler(先进先出调度器)是最简单的调度器,它按照应用程序提交的顺序来分配资源。所有提交的应用程序被放入一个队列中,先提交的应用程序先获得资源,只有当前面的应用程序运行完成或者释放了足够的资源后,后面的应用程序才能得到调度。这种调度器的优点是实现简单,不需要复杂的配置,适用于对资源利用率要求不高、应用程序之间没有严格的资源隔离需求的场景,比如一些测试环境或者单用户的小型集群。然而,它的缺点也很明显,如果有一个大的应用程序占用了大量资源且运行时间较长,那么后面提交的小应用程序就需要长时间等待,导致应用程序并发运行程度低,无法满足多租户环境下不同用户对资源的公平使用需求。
Capacity Scheduler(容量调度器)以队列为单位划分资源,允许多个组织共享一个 Hadoop 集群。每个队列可以设定一定比例的资源最低保证和使用上限,比如可以设置队列 A 保证获得 30% 的集群资源,最多使用 50% 的集群资源。每个队列内部采用 FIFO 调度策略,当一个队列中的资源有剩余时,可以共享给其他队列使用,提高资源利用率。同时,为了防止单个用户的应用程序占用过多资源,还可以对每个用户可使用的资源量设置上限。这种调度器适合多用户共享集群的场景,能够保证每个队列和用户都能获得一定的资源份额,避免资源被某个应用程序或用户独占,比如在企业中,不同部门的应用程序可以放在不同的队列中,根据业务需求为每个部门分配相应的资源。
Fair Scheduler(公平调度器)支持多个队列,每个队列可以配置一定的资源,每个队列中的应用程序公平共享其所在队列的所有资源。它的公平性体现在,当所有应用程序同时请求资源时,会尽量为每个应用程序分配相等的资源份额 ;如果某个应用程序长时间没有得到资源,它会优先获得资源分配,以保证公平性。队列中的应用程序按照优先级分配资源,优先级越高分配的资源越多,优先级是根据每个应用程序的理想获取资源量减去实际获取资源量的差值决定的,差值越大优先级越高。这种调度器适用于多个应用程序之间需要公平竞争资源的场景,比如在一个数据处理平台上,不同的数据分析任务可以在公平的资源分配下同时运行,避免某些任务因为资源分配不均而长时间等待。
5.3 YARN 应用提交与运行
在 YARN 上提交和运行应用程序涉及客户端与 YARN 各组件之间的一系列交互过程。
当用户想要在 YARN 上运行一个应用程序时,首先通过客户端提交应用程序。客户端会向 ResourceManager 申请一个 Application,类似于向公司领导申请一个项目的开展许可。ResourceManager 会为这个应用程序分配一个唯一的 Application ID,并返回给客户端该应用程序资源的提交路径。客户端将应用程序的相关资源,如程序代码、配置文件、依赖的库等,上传到指定的提交路径,就像将项目所需的各种资料准备好并放置到指定位置。然后,客户端向 ResourceManager 申请运行 ApplicationMaster,这是应用程序运行的关键步骤。
ResourceManager 接收到客户端的请求后,会在某个 NodeManager 上为该应用程序分配一个 Container,并要求这个 NodeManager 在这个 Container 中启动 ApplicationMaster。NodeManager 收到命令后,会按照要求启动 ApplicationMaster。ApplicationMaster 启动后,会首先向 ResourceManager 注册自己,就像新入职的员工向公司登记自己的信息,这样客户端就可以通过 ResourceManager 查询到该应用程序的运行状态。
接下来,ApplicationMaster 会根据应用程序的需求,向 ResourceManager 申请运行任务所需的 Container 资源,说明需要多少个 Container 以及每个 Container 需要的资源量。ResourceManager 根据集群的资源情况和调度策略,为 ApplicationMaster 分配 Container 资源,并将分配结果返回给 ApplicationMaster。ApplicationMaster 收到分配的 Container 后,会与对应的 NodeManager 通信,要求 NodeManager 启动这些 Container 中的任务,NodeManager 会按照 ApplicationMaster 的要求启动任务。
在任务运行过程中,各个任务会通过 RPC 向 ApplicationMaster 汇报自己的状态和进度,让 ApplicationMaster 随时掌握任务的执行情况。如果某个任务失败,ApplicationMaster 会根据情况为该任务重新申请资源并重启任务。客户端可以直接与 ApplicationMaster 通信,获取应用程序的运行状态、进度更新等信息,以便用户了解应用程序的执行情况。
当所有任务都运行完成后,ApplicationMaster 会向 ResourceManager 注销自己,并通知 ResourceManager 可以回收该应用程序使用的 Container 资源,整个应用程序运行结束。
六、总结与展望
通过对这些 Hadoop 面试题的探讨,我们深入了解了 Hadoop 分布式计算平台的基础概念、运行模式以及核心组件 HDFS、MapReduce 和 Yarn 的工作原理与关键机制。Hadoop 作为大数据领域的基石,其重要性不言而喻,无论是数据的存储、处理还是资源的管理调度,都展现出强大的功能和优势。在面试中,对这些知识点的熟练掌握能让你脱颖而出。但 Hadoop 的知识体系庞大且不断发展,仅仅了解这些面试题是远远不够的。建议读者进一步深入学习 Hadoop 的高级特性,如 Hadoop 的安全机制、性能调优技巧,以及 Hadoop 与其他大数据技术的融合应用。可以通过阅读官方文档、参考专业书籍、参与实际项目以及在社区中与同行交流等方式,不断积累经验,提升自己对 Hadoop 的理解和应用能力。希望大家都能在 Hadoop 的学习之路上收获满满,顺利通过面试,开启大数据领域的精彩职业生涯。