一、HDFS 相关问

  1. 请简述HDFS的架构及其核心组件。
  2. HDFS的块(Block)默认大小是多少?为什么设置这么大?
  3. HDFS的写入流程是怎样的?
  4. HDFS的读取流程是怎样的?
  5. NameNode和SecondaryNameNode有什么区别与联系?
  6. 什么是“机架感知”(Rack Awareness)?它的策略是什么?
  7. HDFS如何保证数据的可靠性?

二、MapReduce 相关问题

  1. 请简述MapReduce的核心思想。
  2. 一个完整的MapReduce程序包含哪些主要阶段?
  3. Shuffle阶段的具体过程是怎样的?
  4. Combiner的作用是什么?它和Reducer的区别?
  5. MapReduce中的Partitioner的作用是什么?
  6. 如果没有定义Partitioner,数据是如何路由到Reducer的?
  7. 简述MapReduce的作业提交流程(YARN之前和之后)。

三、YARN 相关问题

  1. 为什么会有YARN?它解决了什么问题?
  2. 请简述YARN的架构及其核心组件。
  3. 请详细描述一个作业提交到YARN上的完整流程。
  4. YARN中的Scheduler(调度器)有哪几种?它们有什么区别?
  5. Container是什么?
  6. ApplicationMaster(AM)的主要职责是什么?

四、综合与调优问题

  1. Hadoop有哪些主要的优化手段?
  2. Hadoop的小文件问题是什么?如何解决?
  3. Hadoop 1.x和Hadoop 2.x的主要区别是什么?
  4. 什么是Speculative Execution(推测执行)?它的原理是什么?
  5. 如何在MapReduce中实现自定义的Writable数据类型?

一、HDFS 相关问题

1. 请简述HDFS的架构及其核心组件。

:HDFS采用主从(Master/Slave)架构。

  • NameNode (主节点/Master):负责管理文件系统的命名空间(Namespace),存储元数据(如文件名、目录结构、文件块信息、块所在DataNode列表等)。它不存储实际数据。
  • DataNode (从节点/Slave):负责存储实际的数据块(Blocks),并定期向NameNode发送心跳(Heartbeat)和块报告(BlockReport)。
  • Secondary NameNode (辅助节点):它的主要职责是定期合并NameNode的镜像文件(fsimage)和编辑日志(edits),以防止日志文件过大。注意:它不是NameNode的热备,其目的是帮助主NameNode更高效地工作。

2. HDFS的块(Block)默认大小是多少?为什么设置这么大?

:Hadoop 2.x及之后版本的默认块大小是128MB(早期1.x版本是64MB)。设置这么大的主要原因有:

  • 减少寻址开销:块变大,相对于大量数据,寻址时间占比变小,传输效率更高。
  • 减少NameNode内存消耗:块是元数据管理的基本单位,更大的块意味着文件被切分成更少的块,从而减少了NameNode需要维护的元数据量。

3. HDFS的写入流程是怎样的?

  1. 客户端向NameNode发起文件上传请求,NameNode检查目标文件是否存在及权限。
  2. NameNode响应客户端,告知其可以写入哪些DataNode(返回一个DataNode列表)。
  3. 客户端将文件切分成多个Packet(数据包),并写入到一个数据管道(Pipeline)中。管道由返回的DataNode列表组成。
  4. Packet依次流经管道中的各个DataNode,每个DataNode成功存储数据块后,会向上游节点发送ACK确认。
  5. 所有数据块写入完成后,客户端通知NameNode写入完成,NameNode提交元数据。

4. HDFS的读取流程是怎样的?

  1. 客户端向NameNode请求下载文件。
  2. NameNode返回文件的部分或全部块列表以及每个块所在的DataNode地址。
  3. 客户端根据网络拓扑,选择离自己最近的DataNode建立连接,并行读取数据块。
  4. 数据从DataNode流式传输到客户端。
  5. 客户端将读取到的所有块合并成一个完整的文件。

5. NameNode和SecondaryNameNode有什么区别与联系?

  • 区别
  • NameNode:管理元数据,接收Client和DataNode的请求,是核心主节点。
  • SecondaryNameNode:辅助NameNode,定期合并fsimage和edits文件,但不是热备,当NameNode宕机时,它无法立即接管服务。
  • 联系:SecondaryNameNode会定期从NameNode下载fsimage和edits文件,在本地合并,然后将新的fsimage推送给NameNode,帮助其减轻启动和运行压力。

6. 什么是“机架感知”(Rack Awareness)?它的策略是什么?

:机架感知是HDFS为了数据可靠性和高效网络传输而设计的功能。NameNode知道每个DataNode所属的机架ID。

  • 副本放置策略(默认):
  1. 第一个副本放在客户端所在的机架(如果客户端不在集群内,则随机选择)。
  2. 第二个副本放在另一个机架的一个随机节点上。
  3. 第三个副本放在第二个副本所在机架的另一个节点上。 这样既保证了跨机架的容错能力,又减少了跨机架的数据传输(同一机架内传输带宽更高)。

7. HDFS如何保证数据的可靠性?

  • 多副本机制:默认每个数据块有3个副本,分散在不同机架和节点上。
  • 心跳机制:DataNode定期向NameNode发送心跳,NameNode据此判断DataNode是否存活。
  • 数据校验:客户端写入数据时会计算校验和(Checksum),并一同写入。读取时也会验证校验和,发现损坏则从其他副本读取。
  • 副本自动补充:NameNode检测到某个块的副本数量低于设定值,会启动副本复制流程。
  • 安全模式:系统启动时,NameNode会进入安全模式,此时不对外提供写服务,等待DataNode上报块信息,确认数据块达到最小副本数要求。

二、MapReduce 相关问题

8. 请简述MapReduce的核心思想。

:MapReduce的核心思想是 “分而治之”(Divide and Conquer)

  1. Map阶段:将一个大任务拆分成多个小任务(Map Task),并行处理输入数据,输出中间结果(key-value对)。
  2. Shuffle阶段:对Map输出的中间结果进行分区(Partitioning)、排序(Sorting)、分组(Grouping)后,分发到对应的Reduce节点。
  3. Reduce阶段:对接收到的属于同一个key的中间结果进行聚合计算,输出最终结果。

9. 一个完整的MapReduce程序包含哪些主要阶段?

Input -> Map -> Combiner (可选) -> Shuffle -> Reduce -> Output

10. Shuffle阶段的具体过程是怎样的?(这是超级高频问题!)

:Shuffle是连接Map和Reduce的桥梁,分为Map端的Shuffle和Reduce端的Shuffle。

  • Map端
  1. Partition & Sort:Map Task的输出先被写入一个环形内存缓冲区(Buffer),当缓冲区达到一定阈值(80%),会启动一个后台线程将数据溢写(Spill) 到磁盘。溢写前,会对数据按key进行分区(Partition)和排序(Sort)
  2. Combine (可选):如果设置了Combiner,会在排序后的溢写文件上进行本地聚合,减少磁盘IO和网络传输。
  3. Merge:所有Map Task完成后,会将多个溢写文件合并(Merge) 成一个已分区且排序的大文件。
  • Reduce端
  1. Copy:Reduce Task启动拷贝线程(Fetcher),通过HTTP方式从各个Map Task所在节点拉取(Fetch)属于自己分区的数据。

  2. Merge:一边拉取数据,一边将数据合并到内存和磁盘中。

  3. Sort:最后对所有数据进行一次归并排序,将相同key的value组合在一起,形成<key, (list of values)>的格式提供给Reduce函数处理。

11. Combiner的作用是什么?它和Reducer的区别?

  • 作用:Combiner是一个本地的Reducer,它在Map端对输出进行初步的合并,减少Map输出到Reduce端的数据量,从而降低网络传输开销。
  • 区别
  • 执行位置:Combiner在Map端执行;Reducer在Reduce端执行。
  • 输出:Combiner的输出是Reducer的输入。
  • 可选项:Combiner是可选的,并不一定适用所有场景(例如求平均值就不行);Reducer是必需的。

12. MapReduce中的Partitioner的作用是什么?

:Partitioner(分区器)决定了Map Task输出的每个key-value对应该被发送到哪个Reduce Task进行处理。默认的分区器是HashPartitioner,它通过对key进行哈希值取模来分配分区,确保相同key的数据一定进入同一个Reduce Task。

13. 如果没有定义Partitioner,数据是如何路由到Reducer的?

:如果没有自定义Partitioner,会使用默认的HashPartitioner

它的工作方式是:对每个键(Key)的哈希码(hashCode)取模运算(%),模数为 Reduce Task 的个数。计算公式为:

partition = (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks

这个计算确保了数据被相对均匀地分发到各个 Reducer 上。

14. 简述MapReduce的作业提交流程(YARN之前和之后)。

  • YARN之前(Hadoop 1.x):客户端提交Job给JobTracker。JobTracker负责资源管理和作业调度。TaskTracker通过心跳从JobTracker领取任务并执行。
  • YARN之后(Hadoop 2.x+)
  1. 客户端向ResourceManager(RM)提交Job。
  2. RM找一个NodeManager(NM)启动ApplicationMaster(AM)。
  3. AM向RM申请运行任务所需的资源(Container)。
  4. RM分配资源后,AM与对应的NM通信,在Container中启动MapTask或ReduceTask。
  5. AM监控所有任务的执行状态和进度。

三、YARN 相关问题

15. 为什么会有YARN?它解决了什么问题?

:YARN是为了解决Hadoop 1.x中MapReduce计算框架的局限性而诞生的。

  • 解决的问题
  1. 扩展性差:JobTracker同时负责资源管理和作业调度,压力大,成为集群瓶颈。
  2. 资源利用率低:资源被强制划分为Map Slot和Reduce Slot,无法灵活共享。
  3. 不支持多种计算框架:仅限于运行MapReduce作业,无法支持Spark、Flink等其他计算框架。 YARN将资源管理和作业调度/监控分离,成为一个通用的集群资源管理系统

16. 请简述YARN的架构及其核心组件。

:YARN也是主从架构。

  • ResourceManager (RM - 主节点):整个集群资源的管理和调度者。主要有两个组件:
  • 调度器(Scheduler):根据容量、队列等限制,将系统资源分配给各个正在运行的应用程序。
  • 应用程序管理器(Applications Manager):负责管理所有应用程序的ApplicationMaster。
  • NodeManager (NM - 从节点):每个节点上的代理,负责管理本节点的资源(CPU、内存等)和使用情况,并向RM汇报,同时执行RM和AM的命令。
  • ApplicationMaster (AM):每个应用程序一个。负责向RM申请资源,与NM通信以启动和监控任务(如MapTask和ReduceTask),并监控任务执行状态。
  • Container:YARN中的资源抽象(包含CPU、内存等资源),任务运行在Container中。

17. 请详细描述一个作业提交到YARN上的完整流程。

:(这是YARN最核心的问题)

  1. 作业提交:Client向RM提交应用程序(如MapReduce Job)。
  2. 启动AM:RM找到一个NM,为其分配一个Container,并在该Container中启动这个应用程序的AM。
  3. 注册与申请资源:AM向RM注册自己,然后为内部的任务(MapTask)向RM的调度器申请资源(Container)。
  4. 分配资源:RM根据调度策略,为AM分配资源。
  5. 启动任务:AM与分配到的Container所在的NM通信,要求NM在Container中启动任务(如MapTask)。
  6. 执行与监控:任务在Container中执行,并向AM汇报进度和状态。
  7. 完成与注销:应用程序运行完成后,AM向RM注销并关闭自己,RM回收所有资源。

18. YARN中的Scheduler(调度器)有哪几种?它们有什么区别?

:主要有三种:

  • FIFO Scheduler(先进先出):将所有应用放入一个队列,按提交顺序执行。简单,但不适合共享集群(大作业会占用所有资源)。
  • Capacity Scheduler(容量调度器)Apache Hadoop默认的调度器。将资源划分为多个队列,每个队列可配置一定的资源保证。队列内部是FIFO。支持弹性分配(一个队列资源空闲时,可以临时借给其他队列),资源利用率高。
  • Fair Scheduler(公平调度器):CDH默认。旨在让所有应用在一段时间内能公平地共享资源。当一个新应用提交时,可以从正在运行的应用中“抢”回一部分资源,使其也能尽快执行。更适合多用户、多任务的场景。

19. Container是什么?

:Container是YARN中对资源的抽象,它封装了某个节点上的多维度资源,如CPU核心数、内存大小等。所有任务(MapTask、ReduceTask,甚至是AM本身)都是在Container中运行的。可以将Container理解为一个“资源容器”。

20. ApplicationMaster(AM)的主要职责是什么?

  • 向ResourceManager申请和协商资源(Container)。
  • 与NodeManager通信,启动、停止和监控任务。
  • 跟踪任务的执行状态和进度,并向ResourceManager汇报。
  • 在任务失败时,申请新资源以重启任务。

四、综合与调优问题

21. Hadoop有哪些主要的优化手段?

  • 硬件选择:使用多磁盘,避免使用RAID(JBOD更好),万兆网络。
  • 压缩:对Map的输入/输出、Reduce的输出进行压缩,减少磁盘IO和网络IO(如使用Snappy、LZO等高速压缩格式)。
  • Combiner:在Map端进行本地聚合。
  • 小文件问题:使用Har归档、SequenceFile、CombineFileInputFormat或将小文件合并成大文件后再处理。
  • JVM调优:调整Map和Reduce Task的堆大小,启用重用等。
  • Shuffle调优:调整缓冲区大小、溢写比例、合并因子等参数。

22. Hadoop的小文件问题是什么?如何解决?

  • 问题:大量小文件会产生巨大的元数据,给NameNode内存带来极大压力;同时,处理大量小文件会生成大量Map Task,效率极低。
  • 解决方案
  1. 数据源头:尽量在数据生成的源头就将小文件合并成大文件(如Flume、Logstash等)。
  2. Har归档 (Hadoop Archive):将大量小文件打包成.har文件,减少NameNode元数据量,但读取时需要额外索引。
  3. 使用SequenceFile:将小文件以key-value形式存储到SequenceFile中,key为文件名,value为文件内容。
  4. 使用CombineFileInputFormat:在MapReduce处理时,将多个小文件“打包”成一个InputSplit,让一个MapTask处理多个小文件。

23. Hadoop 1.x和Hadoop 2.x的主要区别是什么?

:最核心的区别是引入了YARN

  • Hadoop 1.x:以MapReduce为中心,由JobTracker和TaskTracker组成,存在单点瓶颈和扩展性问题。
  • Hadoop 2.x:引入了YARN实现资源管理与作业调度分离,使Hadoop从一个单一的MapReduce系统进化成一个通用的数据平台,可以运行多种计算框架(如MR, Spark, Flink)。

24. 什么是Speculative Execution(推测执行)?它的原理是什么?

  • 定义:当一个作业的某些任务运行速度明显慢于其他同类任务时,Hadoop会在另一个节点上启动一个相同的备份任务(Speculative Task)同时处理相同的数据。哪个任务先完成,就用哪个的结果。
  • 原理:解决由硬件老化、软件Bug或网络拥堵等引起的“拖后腿”问题,防止个别慢任务延长整个作业的执行时间。注意:对于资源紧缺的集群,建议关闭此功能。

25. 如何在MapReduce中实现自定义的Writable数据类型?

:需要实现Hadoop的Writable接口,并重写两个核心方法:

  1. write(DataOutput out):定义如何将对象数据序列化到输出流。
  2. readFields(DataInput in):定义如何从输入流中反序列化数据来填充对象字段。 此外,最好重写toString()hashCode()equals()等方法,以便于使用和调试。

示例(一个自定义的PairWritable):

public class PairWritable implements Writable {
    private String first;
    privateint second;

    // 构造方法、getter/setter...

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeUTF(first);
        out.writeInt(second);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        this.first = in.readUTF();
        this.second = in.readInt();
    }

    // 重写toString等方法...
}

希望这份清单能对您的面试准备有所帮助!请务必在理解的基础上进行记忆,并结合自己的实践经验来回答问题。