[toc]
Spark 面试高频全集(核心原理 + 项目难点 + 踩坑 + 性能调优)
精简面试背诵版,全部是工作实战 + 面试官必问,直接背就能用。
一、Spark 基础高频必问
1. Spark 核心架构
- Driver:调度任务、生成 DAG、划分 Stage、维护元数据
- Executor:执行 Task、负责内存计算、存储缓存数据
- ClusterManager:Yarn/Standalone/K8s 资源调度
- Application:整个 Spark 应用程序
2. 核心概念:RDD、DAG、Stage、Task
- RDD:弹性分布式数据集,不可变、分区、惰性求值
- DAG:任务有向无环图,宽窄依赖划分
- Stage:遇到Shuffle就切分 Stage,上游结果给下游
- Task:一个分区对应一个 Task,并行执行
3. 窄依赖 & 宽依赖(必问)
- 窄依赖:子 RDD 只依赖一个父 RDD,无 Shuffle,流水线执行
- 宽依赖:子 RDD 依赖多个父 RDD,产生 Shuffle,划分 Stage
4. Spark 运行模式
Yarn(生产最常用)、Standalone、Local、K8s
5. Spark 两种调度模式
- FIFO:先来先执行
- FAIR 公平调度:资源均分,多任务互不抢占
6. 缓存级别 Cache & Persist
1 | MEMORY_ONLY`、`MEMORY_AND_DISK`、`MEMORY_ONLY_SER |
生产常用:MEMORY_AND_DISK 内存不够落盘
7. Spark SQL 核心优化
Catalyst 优化器、逻辑计划 / 物理计划、谓词下推、列裁剪、常量折叠
8. Shuffle 是什么
数据按照Key 重新分区、跨节点传输,是 Spark 最耗性能、最容易出问题的环节。
9. Spark 分区原则
分区数决定 Task 数量;
分区太少:并行度低、执行慢;
分区太多:任务过小、调度开销大。
10. Spark 和 Flink 区别
Spark 是微批,离线强、准实时;
Flink 是原生流,事件时间、水位线、低延迟、Exactly-Once 更强。
二、Spark 项目常见难点 & 实战坑(面试官最爱深挖)
1. 数据倾斜(Spark 头号问题)
现象:个别 Key 数据量巨大,某个 Task 执行极慢,整体任务拖很久、OOM。
原因:热点用户、空值过多、分区键分布不均。
解决:
- 热点 Key 加盐打散,局部聚合再全局聚合
- 空值单独过滤或单独分区
- 提高倾斜 Key 所在分区并行度
- 使用
salting加盐、分治 Join
2. Shuffle 量大、任务跑的慢
现象:Shuffle 读写磁盘、网络传输大,耗时占比极高。
解决:
- 尽量提前过滤数据、减少 Shuffle 数据量
- 合理设置 Shuffle 分区数
- 能用 map 端聚合就不要等到 reduce
3. OOM 内存溢出(最常见)
分三种:
-
Driver OOM:收集太多数据、collect 拉取全量数据
-
Executor OOM:分区数据太大、缓存过多、笛卡尔积
-
Shuffle OOM
:Shuffle 文件过大、缓冲区溢出
解决
:
- 增大 Driver/Executor 内存
- 避免
collect()拉大表 - 合理分区、过滤无用数据、少用笛卡尔积
- 调整 Shuffle 缓冲区、排序缓冲区大小
4. 小文件问题(落地 Hive/HDFS)
现象:任务跑完生成几百上千个小文件,占用 NN 内存、查询极慢。
原因:分区过多、Task 数量太多、每次增量输出碎片化。
解决:
- 控制输出分区数、重分区
coalesce/repartition - 写入前合并分区
- 定时离线合并小文件
5. 分区数据倾斜、数据空分区多
现象:有的分区几百 MB,有的分区几 KB 甚至空分区。
解决:重分区、动态调整分区数、过滤无效数据。
6. 谓词不下推、全表扫描
现象:明明加了 where 条件,还是扫描全表。
原因:函数嵌套、子查询复杂、分区字段没写对。
解决:尽早过滤、条件放最外层、分区过滤优先。
7. 缓存滥用导致内存不足
现象:大量 RDD/DataFrame 缓存不释放,集群内存被占满。
解决:不用立刻 unpersist,只缓存高频复用中间表。
8. Join 顺序不对导致性能爆炸
现象:大表 join 大表、小表放后面,没走 Broadcast。
解决:小表放左边、开启自适应广播 Join、手动 Hint。
三、Spark 性能调优全套(面试直接背)
1. 资源参数调优
- 合理设置 Executor 内存、核数
- Driver 内存适当加大,避免收集数据 OOM
- 每个 Executor 核数不宜过多,防止 CPU 上下文切换
2. 分区数调优
- 分区数 = 核心数 2~3 倍最佳
- 避免分区过少并行低、过多调度开销大
- 用
repartition/coalesce控制输出文件数量
3. Shuffle 调优
- 合理设置
spark.sql.shuffle.partitions - 调优 Shuffle 缓冲区、排序缓冲区
- 尽量减少 Shuffle 次数,能合并算子就合并
4. 数据倾斜调优
- 空值过滤、单独处理
- 热点 Key 加盐打散、分两阶段聚合
- 大 Key 单独拆分任务
5. 算子优化
- 尽早过滤、列裁剪、谓词下推
- 避免笛卡尔积、避免不必要的 Join
- 少用
collect、take拉取大量数据到 Driver
6. 缓存优化
- 只缓存复用多次的中间结果
- 用完立即释放
unpersist - 优先内存 + 磁盘缓存级别
7. Join 优化
- 大表 Join 小表走 Broadcast 广播 Join
- 调整 Join 顺序、小表前置
- 避免大表 Join 大表,拆分成中间结果
8. 自适应参数开启
Spark3.x 开启自适应:
动态调整分区、自动倾斜优化、自动广播 Join,大幅减少手动调优成本。
四、面试 30 秒口述满分总结
Spark 基于 RDD 惰性求值、DAG 宽窄依赖划分 Stage,核心瓶颈在Shuffle 和数据倾斜;
项目中常遇到数据倾斜、OOM 内存溢出、Shuffle 量大、落地小文件过多、谓词不下推、Join 效率低等问题;
调优主要从资源参数、分区数量、Shuffle 配置、数据倾斜打散、算子逻辑优化、缓存合理使用、广播 Join、自适应执行入手,减少 Shuffle 开销、控制内存占用、合并小文件,提升任务运行效率和稳定性。
五、可直接写简历的 Spark 项目描述
基于 Spark/Spark SQL 负责离线数仓分层建模、海量日志清洗、维度关联、指标聚合开发;解决数据倾斜、任务 OOM、Shuffle 性能瓶颈、HDFS 小文件泛滥等问题;通过分区调优、Shuffle 参数优化、热点 Key 加盐打散、广播 Join、合理缓存与资源调优等方式,大幅缩短任务运行时长,保障离线数仓准时稳定产出。
Spark Structured Streaming 完整版合集
包含:高频 10 题标准答案 + 底层原理 + 与 Spark Streaming/Flink 对比 + 项目实战坑点 + 性能调优,全合并可直接背诵、面试通用。
一、基础高频 10 题(极简标准答案)
1. 什么是 Spark Structured Streaming?
Spark 新一代流式引擎,基于 DataFrame/Dataset 统一 API,把实时流视作无限增长的动态表,支持 SQL 开发;底层默认微批轮询调度。
2. 底层是微批还是真流式?
默认微批轮询触发,不是事件驱动;仅 Continuous 连续模式为真流式,但生产不稳定、功能阉割,基本不用。
3. 和老版 Spark Streaming 区别?
老版基于 DStream 低级 API,已淘汰;
SSS 用 DataFrame/SQL 更简洁,支持事件时间、窗口、 Exactly-Once,引擎优化更强,语义更标准。
4. 支持哪几种时间语义?
支持处理时间、事件时间;自带水位线和窗口机制,但乱序、迟到数据处理能力远弱于 Flink。
5. Trigger 触发方式有几种?
- 默认微批:固定间隔轮询触发
- 一次性触发:消费完存量数据即停止
- Continuous 连续触发:真流式低延迟,生产极少落地
6. 如何实现 Kafka 消费 Exactly-Once?
依赖Checkpoint 保存 Kafka 偏移量 + 作业状态,引擎保证偏移量不丢不重;
业务层配合唯一主键幂等写入,端到端实现精确一次。
7. Checkpoint 的作用是什么?
周期性保存Kafka 偏移量、算子聚合状态、执行计划元数据;任务重启 / 故障可自动恢复,保证不丢数据、不重复消费。
8. 支持哪些窗口?
支持滚动、滑动、会话窗口,可基于事件时间;
但缺少完善空闲流标记、精细迟到兜底,复杂时序场景不如 Flink。
9. 能做实时数仓吗?
适合简单准实时(1~5 分钟延迟);
乱序严重、要求秒级低延迟、长期大状态聚合,不适合,优先 Flink。
10. SSS 和 Flink 怎么选型?
熟悉 Spark 栈、业务不乱序、仅需准实时、想用统一 SQL 开发;选 Structured Streaming。
要求低延迟、乱序明显、窗口精准、大状态常驻、强 Exactly-Once;选 Flink。
二、Spark Streaming / SSS / Flink 三者对比
核心模型一句话
- Spark Streaming:固定间隔纯微批,DStream 老旧 API,已淘汰。
- Spark Structured Streaming:API 封装成流,底层默认仍是微批轮询;Continuous 为真流但生产不用。
- Flink:原生事件驱动流,来一条处理一条,不是微批。
对比总表
表格
| 框架 | 计算模型 | 延迟 | 时间语义 | 窗口乱序 | 状态管理 | 生产常用 |
|---|---|---|---|---|---|---|
| Spark Streaming | 固定微批 | 秒~分钟级 | 处理时间为主 | 弱,无完善乱序 | 无原生状态 | 已淘汰 |
| Structured Streaming | 默认微批;Continuous 真流 | 百 ms~ 秒级 | 支持事件时间 | 中等,水位线偏弱 | 有状态但能力一般 | 准实时简单实时 |
| Flink | 原生事件驱动流 | 毫秒~秒级 | 完善 EventTime | 水位线 + 迟到 + 侧输出全套 | 原生 RocksDB+TTL + 增量 CK | 复杂实时首选 |
延迟排序
Flink (毫秒级) < Structured Streaming (百毫秒) < Spark Streaming (秒级以上)
三、项目实战常见坑 & 问题现象 + 原因 + 解决方案
坑 1:底层微批导致延迟降不下去
现象:延迟最低只能到几百毫秒,压不到毫秒级。
原因:默认按固定间隔轮询触发 Job,不是事件驱动。
解决:接受准实时定位;超低延迟业务改用 Flink。
坑 2:Checkpoint 目录损坏、任务重启失败
现象:改动代码、升级版本后,从旧 CK 重启直接报错。
原因:SSS 的 CK 绑定执行计划,算子变更、字段增减、逻辑改动后旧 CK 不兼容。
解决:版本迭代换新 CK 目录;上线前清空旧状态,不要复用历史 CK。
坑 3:Kafka 重复消费、落地数据重复
现象:任务重启后产生重复数据。
原因:CK 未完成就重启、手动重置偏移量,偏移量回退。
解决:开启 CK 自动管理偏移量;落地端用唯一主键幂等、主键冲突忽略写入。
坑 4:窗口计算不准、乱序数据对不上离线
现象:晚到数据没被窗口纳入,指标偏小。
原因:水位线推进弱,无空闲流标记、无迟到兜底。
解决:合理设置事件时间水位线;业务上容忍准实时误差,复杂乱序改用 Flink。
坑 5:状态持续膨胀、任务 OOM
现象:运行越久内存占用越高,频繁 GC、OOM。
原因:SSS 无原生状态 TTL,旧 Key 状态不会自动清理。
解决:业务层手动做过期清理;拆分任务生命周期;大状态场景换 Flink RocksDB+TTL。
坑 6:输出大量 HDFS 小文件
现象:持续微批输出,每个批次生成少量文件,小文件爆炸。
原因:微批频繁触发,每次输出都生成新文件。
解决:调大触发间隔攒批;控制输出分区数;离线定时合并小文件。
坑 7:任务自动重启、批次积压延迟走高
现象:批次堆积、处理跟不上消费,延迟持续上涨。
原因:单批次数据量过大、算子逻辑过重、资源不足。
解决:调小批次触发间隔;过滤前置减少计算量;调高 Executor 资源与并行度。
四、Structured Streaming 性能调优要点
-
微批触发调优
合理设置 Trigger 间隔,兼顾延迟与吞吐,避免过小批次产生小文件。
-
Checkpoint 调优
固定独立 CK 目录;版本迭代必换新目录;不随意复用旧状态。
-
并行度与 Kafka 分区对齐
并行度和 Kafka 分区数保持一致,避免空闲 Task 或数据倾斜。
-
前置过滤与列裁剪
尽早 where 过滤、只读取需要字段,减少微批计算压力与 Shuffle 量。
-
避免大算子与重 Shuffle
减少多轮 Join、distinct;能聚合先聚合,降低每批次数据量。
-
资源参数调优
适当加大 Executor 内存、核数;防止单批次数据过大引发 GC 与 OOM。
-
不滥用 Continuous 模式
低延迟不要强行开连续模式,稳定性差、功能受限,生产不推荐。
五、面试 30 秒口述总结版
Spark Structured Streaming 以 DataFrame/SQL 为统一 API,把流当作动态无限表处理,底层默认仍是微批轮询调度,并非 Flink 那种原生事件驱动流;支持事件时间、窗口和 Checkpoint 偏移量管理,适合 1~5 分钟准实时业务。
项目中常遇到CK 版本不兼容、重复消费、状态膨胀 OOM、窗口不准、HDFS 小文件、批次积压延迟等问题;调优主要从触发间隔、CK 规范、并行度对齐、前置过滤、资源配置入手。
技术选型上简单准实时选 SSS,低延迟、乱序复杂、大状态常驻实时业务优先 Flink。