4. Spark 核心面试题

Spark 是大数据离线数仓的核心计算引擎,本章聚焦面试中最常被追问的三大方向:RDD 与 DataFrame 选型、Shuffle 性能瓶颈与调优、内存管理与 OOM 规避。理解这些底层机制,是区分“会用 Spark”与“懂 Spark”的关键分水岭。

RDD vs DataFrame 选型回答框架 面试官问“选哪个?” 场景:底层控制/自定义算子 场景:结构化数据/性能优先 推荐 RDD (需手动优化序列化、内存) 推荐 DataFrame (Tungsten + 自动优化) 加分话术: “如果业务逻辑需要精确控制分区、使用复杂UDF,我选 RDD; 如果只是SQL查询或ETL,选 DataFrame 享受 Catalyst 优化。”

Q1:说说 RDD 与 DataFrame 的区别,你如何选择?

考察点对 Spark 底层执行引擎的理解(Catalyst、Tungsten);选型依据;性能意识
回答框架① 对比核心差异(schema、序列化、执行优化)→ ② 各自使用场景 → ③ 给出判断标准
简短回答RDD 仅存储 Java 对象,依赖开发者手动优化;DataFrame 包含 schema,利用 Catalyst 进行逻辑/物理优化、Tungsten 生成高效代码。我通常优先选 DataFrame,除非需要自定义分区器或处理非结构化数据。
可能追问如何关闭 Catalyst 优化?DataFrame 的序列化方式?
避坑不要只说“DataFrame 比 RDD 快”而不解释原因;避免将 Dataset(强类型) 与 DataFrame 混淆。

Q2:Spark Shuffle 的性能瓶颈在哪里?你如何调优?

考察点Shuffle 原理(hash vs sort)、磁盘IO、网络传输、数据倾斜处理能力
回答框架① 定位瓶颈(磁盘/网络/GC)→ ② 参数调整(spark.shuffle.*)→ ③ 架构优化(减少 shuffle)
简短回答Shuffle 瓶颈在大量小文件、频繁 spill 和序列化开销。我会调大 spark.shuffle.file.buffer(64k→128k)、开启 bypassMergeThreshold(默认 200),并使用基于排序的 Shuffle(spark.shuffle.manager=sorted)。
可能追问什么时候用 hash shuffle?shuffle service 工作原理?
避坑不要只堆参数而不分析原因;避免在数据倾斜时直接加随机前缀而不解释利弊。

Q3:Spark 内存管理如何分配?OOM 时怎么排查?

考察点统一内存模型 (Unified Memory)、执行与存储内存比例、off-heap
回答框架① 内存区域划分(reserved/存储/执行/其他)→ ② 触发 OOM 原因(数据倾斜/对象膨胀)→ ③ 排查工具 + 调优手段
简短回答执行与存储通过 spark.memory.fraction(默认0.6)共用池,可互相借用。遇到OOM先看 stage 页是否存在倾斜,调大 spark.memory.offHeap.enabled 并设置 offHeap.size 减少 GC。
可能追问spark.memory.storageFraction 作用?如何配置堆外内存?
避坑不要盲目调大 executor memory;避免忽略 off-heap 优势;不要忘记广播变量也能缓解 OOM。
项目案例 STAR 表达结构 Situation 日处理 200亿+ 用户日志 Task ETL 性能提升 40% Action Shuffle调优+内存管理 Result 工期压缩 30% 核心难点与方案 • 数据倾斜:对热点 key 加随机前缀后二次聚合 • 频繁 GC:启用 off-heap + 压缩广播变量 (spark.broadcast.compress=true) • Shuffle 小文件:合并分区 (coalesce) + 调整 spark.shuffle.sort.bypassMergeThreshold=400 面试高频追问 1. 为什么选择 coalesce 而不是 repartition? 2. 随机前缀后如何保证数据正确性?(最终聚合去熵化) 3. 如果 off-heap 仍 OOM 怎么办?(调整 ratio + 启用堆外监控)

项目案例:百亿级用户行为日志 ETL 性能优化

项目名称用户行为实时多维分析平台(离线部分)
业务背景采集并处理每日 200亿+ 条用户埋点日志,清洗后存入 Hive 供分析师使用;原有 ETL 任务平均耗时 5h,经常 OOM 导致失败
规模指标日增量 ~200亿 条记录;150+ 台 executor;Spark 3.2 on YARN
技术栈Spark Core、DataFrame API、Hive、YARN、Kryo 序列化、Off-heap
核心难点① 数据倾斜(部分渠道 ID 聚集 70% 数据);② 频繁 Full GC 导致任务中断;③ Shuffle 阶段产生过多小文件
可迁移回答话术“在百亿级日志场景下,我先通过 reduceByKey(…, numPartitions=…) 控制分区,再对倾斜 Key 加随机前缀实现二次聚合;启用 spark.memory.offHeap.enabled=true 配合统一内存池,将 GC 次数从每10min一次降低到每1h一次;最后通过 coalesce 合并分区减少 shuffle 小文件,整体耗时从5h降至2.5h。”
💡 面试锦囊:面试官追问“RDD 与 DataFrame 选型”时,一定要引出 Tungsten(堆外内存 + 代码生成)和 Catalyst(逻辑/物理优化)两个杀手锏。在 Shuffle 调优项目中,使用“先定位瓶颈→再参数调优→最后架构改进”的三步法会让回答更有层次。
⚠️ 常见误区:不要在 Shuffle 调优中只堆参数(如盲目调大 buffer),一定要结合数据分析(倾斜 key、数据量级);不要混淆“堆外内存”和“堆内内存”的作用范围。