大数据面试题集:Hadoop、Spark 与调优

FreeGuideOnline 最新 2026-06-18

开篇介绍

大数据工程师岗位的面试范围广、深度大,但核心考察点始终围绕分布式计算框架的原理、实战与调优三大块。本教程精选了 Hadoop 与 Spark 生态中最高频的面试真题,并结合实际调优场景给出清晰解答。无论你是初学者正在构建知识体系,还是有经验的开发者准备冲刺大厂,都能在这里找到可直接用于面试的高密度知识点。


一、Hadoop 核心面试题

1. HDFS 的架构与读写流程

问题:请描述 HDFS 的架构,以及一个文件写入和读取的完整过程。

参考答案

HDFS 采用主从架构,包含一个 NameNode(主节点,管理元数据)和多个 DataNode(从节点,存储实际数据块)。文件被切分成 Block(默认 128MB),每个 Block 有多个副本(默认 3),分布于不同 DataNode 以确保容错。

  • 写入流程:客户端请求 NameNode 创建文件,NameNode 检查权限与路径合法性后,返回一组 DataNode 用于存放第一个 Block 的副本。客户端以管道(Pipeline)方式将数据包依次写入第一个 DataNode,再由该节点转发给下一个副本节点,最终确认成功。
  • 读取流程:客户端向 NameNode 请求文件 Block 的位置列表,NameNode 返回排序后的 DataNode 地址(优先返回距离客户端近的节点)。客户端与最近的 DataNode 建立连接,以流式方式读取数据块。

延伸:写出流程图能加分,重点放在“感知机架”策略和副本放置规则。

2. MapReduce 工作原理与 Shuffle 阶段

问题:详细说明 MapReduce 的完整执行流程,重点解释 Shuffle 阶段做了什么。

参考答案

MapReduce 分为 Map 和 Reduce 两个阶段,中间由 Shuffle 衔接。

  • Map 阶段:输入数据被 InputFormat 切分成 InputSplit,每个 Split 启动一个 Map Task,调用用户定义的 map() 函数处理每条记录,输出中间键值对,经 Partitioner 决定去向哪个 Reduce。
  • Shuffle 阶段:Map 端首先将输出写入环形缓冲区,达到阈值后进行溢写(spill),并在溢写过程中完成排序和合并(combiner)。所有溢写文件合并成一个最终文件,同时生成索引文件。Reduce 端通过 HTTP 从各个 Map 节点拉取属于自己的分区数据,再进行归并排序,将相同 Key 的值聚合。
  • Reduce 阶段:对聚合后的数据调用 reduce() 函数,输出最终结果。

关键:Shuffle 是性能瓶颈,回答时突出“数据倾斜”“Combiner 减少网络 IO”“内存缓冲调优”等关键词。

3. HDFS 小文件问题与解决方案

问题:HDFS 为什么不适合存储大量小文件?有哪些解决方法?

参考答案

每个文件(即使是 1KB)在 NameNode 中都会占用约 150 字节的元数据。当小文件数量达到亿级别时,NameNode 内存会出现瓶颈,导致 GC 频繁甚至 OOM。此外,大量小文件会增加 Map Task 的数量,降低计算效率。

解决方案:

  • HAR(Hadoop Archive):将小文件打包成归档文件,底层仍是大量小文件,但元数据项合并为一个。
  • SequenceFile / Avro:使用键值对容器将小文件合并成大文件,适合流式处理。
  • CombineFileInputFormat:让一个 Map Task 处理多个小文件,减少任务启动开销。
  • 外部存储 + 索引:将小文件存入对象存储(如 S3),HDFS 仅存储摘要索引。

4. YARN 的资源调度与队列管理

问题:简述 YARN 的架构,以及 FIFO、Capacity、Fair 三种调度器的区别。

参考答案

YARN 由 ResourceManager(全局资源管理)、NodeManager(节点代理)、ApplicationMaster(应用管理器)组成。

  • FIFO:单队列,任务排队执行,大作业会阻塞后续任务,简单但效率低。
  • Capacity Scheduler:多队列,每个队列分配一定比例资源,硬性限制,适合多租户环境。队列内部可再采用 FIFO 或公平调度。
  • Fair Scheduler:资源动态均衡,任务提交时分配大致相等的资源,超出部分按权重共享,允许抢占,适合任务大小混合的场景。

调优要点:合理配置最小/最大资源、队列权重、抢占策略和最大应用数量。


二、Spark 核心面试题

1. Spark 基本架构与作业执行流程

问题:Spark 程序如何从提交到执行?说明 Driver、Executor、Task 之间的关系。

参考答案

一个 Spark 应用包含一个 Driver 进程和多个 Executor 进程。

  1. 用户提交应用后,Driver 解析代码生成逻辑执行计划(DAG)。
  2. Driver 向集群管理器(Standalone/YARN/K8s)申请 Executor 资源。
  3. Driver 将任务序列化后分发给 Executor 执行,每个 Task 处理 RDD 的一个分区。
  4. Executor 多线程执行 Task,中间结果可缓存或落盘,执行完毕将结果返回 Driver(或直接输出到外部存储)。

关键角色:Driver 负责任务调度和 DAG 生成,Executor 负责实际计算和存储,Task 是最小执行单元。

2. RDD、DataFrame、Dataset 的区别与选择

问题:请对比 RDD、DataFrame 和 Dataset,并说明在不同场景下如何选择。

参考答案

特性 RDD DataFrame Dataset
抽象层次 低阶,分布式对象集合 高阶,关系型表 强类型,结合两者
语言支持 Scala/Java/Python 所有语言 Scala/Java(静态类型)
序列化 Java 序列化或 Kryo Tungsten 优化(堆外内存) Encoder(高效二进制)
优化器 无优化 Catalyst 优化器 Catalyst 优化器
类型安全 编译时安全 运行时检测类型 编译时安全

选择指南

  • 需要底层控制、复杂的 DAG 操作或非结构化数据,使用 RDD
  • 进行关系型查询、聚合分析,偏好 SQL 风格,使用 DataFrame(性能优于 RDD)。
  • 要求编译时类型安全且享受优化加持,语言为 Scala/Java 时,使用 Dataset

3. Spark Shuffle 机制与优化

问题:Spark 的 Shuffle 过程是怎样的?如何优化 Shuffle 带来的性能问题?

参考答案

Spark Shuffle 发生在宽依赖(如 groupByKey、reduceByKey、join)操作中。它涉及数据跨分区的重新分布,分为 Map 端写入和 Reduce 端读取。

优化策略:

  • 使用 map-side 预聚合:优先用 reduceByKey 代替 groupByKey,因为前者支持 Map 端合并,减少 Shuffle 数据量。
  • 调整分区数:通过 spark.sql.shuffle.partitions(默认 200)或 repartition 设置合理的分区数,避免单个 Task 处理过大数据。
  • 内存与磁盘平衡:调大 spark.shuffle.file.buffer(32KB)和 spark.reducer.maxSizeInFlight(48MB)减少 IO 次数。
  • Tungsten 排序优化:利用堆外内存和指针提高排序效率。
  • 使用广播策略:小表 Join 大表时,广播小表避免 Shuffle。

4. Spark Streaming 与 Structured Streaming 对比

问题:说说 Spark Streaming 和 Structured Streaming 有何不同?为什么推荐后者?

参考答案

  • 编程模型:Spark Streaming 基于 DStream,属于微批处理(Micro-batch),窗口元数据需手动管理。Structured Streaming 将流当作无界表,使用增量查询,支持事件时间、窗口聚合更简洁。
  • 容错语义:Structured Streaming 基于检查点(Checkpoint)和预写日志(WAL)提供精确一次(Exactly-once)语义,比 Spark Streaming 更可靠。
  • 端到端 Kafka 集成:Structured Streaming 原生支持 Kafka 源和接收器,并配合 Offset 管理实现事务性写入。
  • 延迟:两种都能达到秒级延迟,但 Structured Streaming 的连续处理模式可降至毫秒级。

实际生产中,新项目建议直接采纳 Structured Streaming。


三、调优专项面试题

1. 数据倾斜的检测与处理

问题:在 Spark 或 MapReduce 中遇到数据倾斜如何解决?

参考答案

数据倾斜表现为某个 Task 处理的数据量或耗时远超其他 Task,常见于 join、groupBy 操作。

解决方案

  • 盐值加盐(Salting):给倾斜的 Key 加上随机前缀(如 "0_"、"1_" 等),打散到多个分区后聚合,再去除前缀做二次聚合。
  • 广播小表:若一张表很小(< 1GB),广播它然后进行 Map-side join,完全避免 Shuffle。
  • 分离倾斜数据:将倾斜的 Key 单独取出处理(膨胀+聚合),正常数据照常处理,最后 Union。
  • 提高并行度:增大 spark.sql.shuffle.partitions 或调用 repartition(n),但治标不治本。
  • 使用随机前缀和扩展:Hive 中可用 DISTRIBUTE BY rand() 等技巧。

2. Spark 内存管理调优

问题:Spark 堆内存如何划分?如何配置以减少 GC 开销?

参考答案

Spark 的内存模型分为:

  • 保留内存:300MB 固定,用于内部机制。
  • 用户内存:由 spark.memory.fraction 控制,默认 0.6 的堆空间用于执行和存储内存。
  • 执行内存:用于 Shuffle、Join、Sort 等操作。
  • 存储内存:用于缓存 RDD/广播变量。

调优手段

  • 执行内存不足时 Spark 会溢写到磁盘,可适当增大 spark.memory.fraction
  • 避免使用 groupByKey 这样需要大量内存的操作,优先使用 reduceByKey
  • 使用 Kryo 序列化减少内存占用(spark.serializer=org.apache.spark.serializer.KryoSerializer)。
  • 监控 GC:设置 -verbose:gc,如果 Full GC 频繁,考虑降低缓存或增大内存。
  • 统一内存管理的堆外内存:开启 spark.memory.offHeap.enabled 可减少 GC 影响。

3. Hive on Spark 与参数调优

问题:Hive 切换到 Spark 执行引擎时,常见调优参数有哪些?

参考答案

  • 并行度set spark.executor.instances=6;set spark.executor.cores=4; 根据集群调整并发。
  • 动态资源分配set spark.dynamicAllocation.enabled=true; 让空闲的 Executor 释放。
  • 小文件合并set hive.merge.sparkfiles=true; 输出时合并小文件。
  • Shuffle 相关set spark.sql.adaptive.enabled=true; 开启自适应查询执行(AQE),自动合并小分区、优化倾斜 Join。
  • 内存配比set spark.executor.memory=4g;set spark.yarn.executor.memoryOverhead=1g; 注意堆外内存开销。

AQE 是关键特性,能达到类似“运行时优化”的效果。


四、总结与面试技巧

  • 体系化回答:架构题要从角色职责、核心流程、异常处理几个维度回答。
  • 结合原理说调优:任何调优手段都要能解释它改变了什么原理,比如“减小 Shuffle 数据量是通过 Map 端合并实现的”。
  • 项目经验包装:将技术点融入真实业务场景,如“在某画像系统中,千万级用户标签 Join 发生倾斜,我们采用 Java 侧加盐+二次聚合”。
  • 保持信心:大数据面试没有标准答案,清晰表达观点和思路比死记硬背更重要。

掌握上述内容,你不仅能应对 Hadoop、Spark 和调优的常规问题,还能在深度追问时展现出扎实的工程思维。祝你面试顺利!