项目1:搭建Spark集群——Spark概述
先修基础:Java、Scala、Linux、Hadoop(HDFS+YARN+MapReduce)、Hive
目录
- 第一部分:Spark 入门概览
- 第二部分:Spark 核心架构与运行原理
- 第三部分:RDD 核心概念与核心原理
- 第四部分:Spark 部署模式详解
- 第五部分:Spark 环境搭建实操(重点)
- 第六部分:Spark 初体验——WordCount & SparkPi
- 第七部分:常见问题与排错指南
- 第八部分:实习 / 面试高频考点
- 第九部分:项目小结
- 附录:选择题解析
第一部分:Spark 入门概览
1.0 项目背景
为什么要学 Spark?
大数据技术及人工智能的蓬勃发展,促进了我国经济更快更好地进入高质量发展阶段,加快建设制造强国、质量强国、航天强国、交通强国、网络强国、数字中国。
目前企业和研究机构使用的大数据处理平台基本都是基于 Hadoop 分布式框架,但 Hadoop 本身还存在诸多缺陷,最主要的缺陷是 MapReduce 计算时延迟过高,无法满足实时、快速计算的需求。
为了满足企业和研究机构对于大规模数据集的实时分析和快速计算的需求,提高数据处理的效率,搭建一个高效的大数据处理平台变得至关重要。
Spark 解决了什么问题?
Spark 继承了 MapReduce 分布式计算的优点并改进了其明显缺陷:
- 中间结果可以保存在内存中,大大减少了读写 HDFS 的次数
- 更适合迭代计算:数据挖掘与机器学习中迭代次数较多的算法,Spark 比 MapReduce 快几十到上百倍
- 一套引擎支持多场景:批处理、SQL查询、流处理、机器学习、图计算,不用学多套框架
Spark 技术不仅加快了数据处理速度,也为我国在建设数字中国、推进智能化转型提供了强有力的技术支撑。
1.1 Spark 是什么
一句话定义:Spark 是 Apache 基金会旗下的一款快速、通用、可扩展的分布式计算引擎,用于大规模数据处理。
可以把 Spark 理解为「Hadoop MapReduce 的升级版 + 全方位扩展版」。它不仅能做离线批处理,还能做实时流计算、SQL查询、机器学习、图计算,而且速度比 MapReduce 快几十到上百倍。
官方与核心文档
- *Apache Spark 官网*:最权威的起点,提供全面的功能介绍、组件说明 以及最新动态。
- *Spark 官方快速入门文档*:适合初学者通过交互式 Shell 快速上手 Python 或 Scala API。
官方定义中的关键词
| 关键词 | 含义 |
|---|---|
| 快速(Fast) | 基于内存计算,比 MapReduce 快 10~100 倍 |
| 通用(Unified) | 一套引擎支持批处理、流处理、SQL、机器学习、图计算 |
| 可扩展(Scalable) | 支持从单机到数千台服务器的横向扩展 |
| 分布式计算引擎 | 不是存储系统,是计算引擎(存储靠 HDFS/HBase 等) |
⚠️ 重要区分:Spark 是计算引擎,不是存储系统。Hadoop 既有存储(HDFS)又有计算(MapReduce),而 Spark 只负责计算,数据可以存在 HDFS、HBase、S3、本地文件系统等任何地方。
1.2 Spark vs Hadoop MapReduce(重点对比)
你们已经学过 Hadoop MapReduce,这张对比表帮你快速建立认知:
| 对比维度 | Hadoop MapReduce | Spark |
|---|---|---|
| 计算模型 | 基于磁盘的两阶段(Map + Reduce) | 基于内存的 DAG 有向无环图 |
| 速度 | 慢(中间结果落盘,IO开销大) | 快(中间结果放内存,减少磁盘IO) |
| 编程模型 | 只能写 Mapper + Reducer,API 低级 | RDD / DataFrame / SQL,API 高级且丰富 |
| 适用场景 | 纯离线批处理 | 离线批处理 + 实时流处理 + SQL + ML + 图计算 |
| 迭代计算 | 非常差(每次迭代都要读写HDFS) | 非常好(数据缓存到内存,迭代极快) |
| 延迟 | 高(分钟/小时级) | 低(秒/毫秒级,流计算场景) |
| 资源调度 | 只能跑在 YARN 上 | 支持 Standalone / YARN / Mesos / K8s |
| 学习曲线 | 入门简单,深入难 | 入门稍陡,但写代码效率高 |
为什么 Spark 比 MapReduce 快?(面试常问)
核心原因有三个:
基于内存计算:MapReduce 每次 shuffle 后都把中间结果写到 HDFS 磁盘;Spark 可以把中间结果缓存在内存中,下一个计算步骤直接读内存,省去大量磁盘 IO。
DAG 调度优化:MapReduce 只有 Map + Reduce 两个阶段,多个任务之间没有优化;Spark 会把多个操作组成一个 DAG(有向无环图),在执行前进行阶段划分和流水线优化,减少不必要的 shuffle。
更高效的 Shuffle 机制:Spark 的 Shuffle 实现比 MapReduce 更高效,支持多种 Shuffle 管理器(SortShuffleManager 等),减少了磁盘 IO 和序列化开销。
💡 形象比喻:MapReduce 就像「每做完一道菜就把锅碗瓢盆全洗一遍再做下一道」;Spark 就像「备菜全部备好,按顺序一气呵成,能复用的绝不重复做」。
1.3 Spark 核心特点
① 速度快(Speed)
- 内存计算,比 Hadoop MapReduce 快 100 倍
- 磁盘计算也比 MapReduce 快 10 倍以上
- 底层使用 DAG 调度引擎、RDD 优化执行

② 易用性(Ease of Use)
- 支持 Scala、Java、Python、R、SQL 多种 API
- 提供超过 80 种高级算子,不用手写 Mapper/Reducer
- 支持交互式 shell(spark-shell / pyspark),边写边跑
③ 通用性(Generality)
一套技术栈覆盖全场景:
- Spark SQL:结构化数据查询,类 SQL 语法
- Spark Streaming / Structured Streaming:实时流计算
- MLlib:机器学习库
- GraphX:图计算库

④ 随处可运行(Runs Everywhere)
- Standalone:Spark 自带的集群管理器(独立模式)
- Hadoop YARN:跑在 Hadoop 集群上(企业最常用)
- Apache Mesos:老牌资源管理器
- Kubernetes:容器化部署(云原生趋势)
- 数据来源支持:HDFS、Cassandra、HBase、Hive、本地文件等
⑤ 容错性(Fault Tolerance)
- RDD 血缘(Lineage)机制:节点挂了,根据依赖关系重新计算即可,不需要冗余备份
- 比传统分布式系统的副本容错更节省资源
⑥ 代码简洁
- Spark 支持使用 Scala、Python 等语言编写应用
- 相比 Java,Scala 和 Python 的代码更为简洁
- 在 Spark 中通常使用 Scala 或 Python 编写应用程序,比在 MapReduce 中编写更简单方便
- 经典对比:使用 MapReduce 实现单词计数可能需要 60 多行代码,而在 Spark 中使用 Scala 语言实现仅需一行代码:
sc.textFile("/user/root/test.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).saveAsTextFile("/user/root/output")💡 记忆口诀:快、易、通、跑、容、简——快速、易用、通用、随处运行、容错、代码简洁
1.4 Spark 生态圈(Spark 四大组件)
Spark 不是一个单一工具,而是一个完整的大数据技术栈,以 Spark Core 为核心,向上扩展出四大组件:
┌─────────────────────────────────────────────────────────┐
│ Spark 生态组件层 │
│ ┌──────────┐ ┌──────────────┐ ┌────────┐ ┌──────────┐ │
│ │ Spark SQL│ │ Structured │ │ MLlib │ │ GraphX │ │
│ │ (SQL) │ │ Streaming │ │ (机器学习)│ │ (图计算) │ │
│ └────┬─────┘ └──────┬───────┘ └───┬────┘ └────┬─────┘ │
│ │ │ │ │ │
│ ┌────┴──────────────┴─────────────┴───────────┴─────┐ │
│ │ Spark Core(核心引擎) │ │
│ │ RDD / 调度 / 内存管理 / 容错 / API │ │
│ └─────────────────────┬─────────────────────────────┘ │
│ │ │
│ ┌─────────────────────┴─────────────────────────────┐ │
│ │ 集群管理器(Cluster Manager) │ │
│ │ Standalone | YARN | Mesos | Kubernetes │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘各组件详解
| 组件 | 作用 | 应用场景 | 学习优先级 |
|---|---|---|---|
| Spark Core | 核心引擎,提供 RDD、调度、内存管理、容错 | 所有 Spark 应用的基础 | ⭐⭐⭐⭐⭐ 必学 |
| Spark SQL | 结构化数据处理,支持 SQL/HQL 查询 | 数据仓库、报表统计、ETL | ⭐⭐⭐⭐⭐ 企业最常用 |
| Structured Streaming | 实时流计算(流批一体) | 实时监控、实时推荐、实时风控 | ⭐⭐⭐⭐ 重点 |
| MLlib | 机器学习算法库 | 分类、回归、聚类、推荐系统 | ⭐⭐⭐ 了解 |
| GraphX | 图计算引擎 | 社交网络、路径规划、社区发现 | ⭐⭐ 了解即可 |
生态圈其他组件(了解)
除了以上五大核心组件,Spark 生态圈还包含以下组件:
| 组件 | 作用 | 说明 |
|---|---|---|
| Spark Streaming | 第一代流计算(DStream) | 已被 Structured Streaming 替代,了解即可 |
| BlinkDB | 权衡查询(近似查询) | 在查询精度和响应时间之间做权衡,大数据量下快速返回近似结果 |
| MLBase | 机器学习平台 | MLlib 的上层封装,更易用的机器学习工具 |
| SparkR | R 语言接口 | 让 R 语言用户可以使用 Spark,适合数据分析师 |
| Alluxio(Tachyon) | 分布式内存文件系统 | 以内存为中心的虚拟分布式存储,加速数据访问 |
支持的数据源
Spark 本身没有存储功能,是纯计算引擎,可以从多种数据源读取数据:
- HDFS:Hadoop 分布式文件系统(最常用)
- HBase:分布式 NoSQL 数据库
- Hive:数据仓库(直接读 Hive 表)
- Cassandra:分布式 NoSQL 数据库
- Amazon S3:AWS 对象存储
- 本地文件系统:Linux/Windows 本地文件
💡 重点提示:企业里用得最多的是 Spark SQL + Spark Core,其次是 Structured Streaming。MLlib 和 GraphX 在普通开发岗用得不多,算法岗才会深入。

1.5 Spark 应用场景
应用场景总览表
| 应用领域 | 描述 | 示例应用 | 对应组件 |
|---|---|---|---|
| 实时数据处理 | Spark Streaming / Structured Streaming 模块使得 Spark 非常适合需要实时数据处理的应用 | 实时日志分析、实时交易监控、实时风控 | Structured Streaming |
| 机器学习和数据挖掘 | 内存迭代计算非常适合机器学习算法的反复迭代训练 | 推荐系统、用户行为分析、分类聚类 | MLlib + Spark Core |
| 图形数据处理 | Spark GraphX 模块在社交网络分析和网络优化问题中表现出色 | 社交网络分析、网络优化、关联图谱 | GraphX |
| 复杂的 ETL 任务 | Spark 能够处理大量的数据转换任务,尤其在数据清洗、转换和加载(ETL)过程中表现优异 | 数据 ETL 过程、数据仓库建设 | Spark SQL + Spark Core |
| 即席查询 / 交互式分析 | Spark SQL 支持快速的 SQL 查询,秒级响应海量数据 | 数据分析师即席查询、报表统计 | Spark SQL |
各场景详解
① 离线数据处理 / 批处理
- 大规模数据 ETL(抽取、转换、加载)
- 数据仓库建设(替代 Hive 的 MapReduce 引擎,跑 Hive SQL 更快)
- 日志分析、用户行为分析
- 报表统计、数据大屏
② 交互式查询 / 即席查询
- 数据分析师用 Spark SQL 快速查询海量数据
- 替代传统数仓的慢查询,秒级响应
③ 实时流处理
- 实时数据监控(如网站实时 PV/UV)
- 实时推荐系统
- 实时风控、欺诈检测
- 物联网(IoT)实时数据处理
④ 机器学习
- 大规模模型训练(推荐算法、分类、聚类)
- 特征工程、模型迭代
⑤ 图计算
- 社交网络关系分析
- 金融风控中的关联图谱
- 路径优化
⚠️ 注意:Spark 不适合什么场景?
- 不适合小数据量(几MB/几GB):杀鸡用牛刀,单机更快
- 不适合毫秒级实时(如股票交易撮合):Spark Streaming 是秒级/亚秒级,不是毫秒级
- 不适合事务型数据库:Spark 不是 OLTP 数据库,不能替代 MySQL
第二部分:Spark 核心架构与运行原理
2.1 Spark 运行架构总览

Spark 采用主从(Master-Worker)架构,核心组件如下:
┌─────────────────────────────────────────────────────────────┐
│ Cluster Manager │
│ (资源调度者:Standalone/YARN/Mesos/K8s) │
└────────┬──────────────────────────────────┬─────────────────┘
│ │
┌────────▼─────────┐ ┌─────────▼──────────┐
│ Worker Node │ │ Worker Node │
│ (工作节点机器) │ │ (工作节点机器) │
│ │ │ │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Executor │ │ │ │ Executor │ │
│ │ (执行进程) │ │ │ │ (执行进程) │ │
│ │ │ │ │ │ │ │
│ │ ┌──────────┐ │ │ │ ┌──────────┐ │ │
│ │ │ Task 1 │ │ │ │ │ Task 1 │ │ │
│ │ ├──────────┤ │ │ │ ├──────────┤ │ │
│ │ │ Task 2 │ │ │ │ │ Task 2 │ │ │
│ │ └──────────┘ │ │ │ └──────────┘ │ │
│ └──────────────┘ │ └──────────────────┘ │
└──────────────────┘ └──────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ Driver Program(驱动程序) │
│ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ SparkContext │ │ DAG Scheduler │ │
│ │ (上下文) │ │ (DAG调度器) │ │
│ └──────────────┘ └──────────────────┘ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │Task Scheduler│ │ Shuffle Manager │ │
│ │ (任务调度器) │ │ (Shuffle管理器) │ │
│ └──────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────┘核心组件详解
① Cluster Manager(集群管理器)
- 作用:负责整个集群的资源分配和管理,相当于「集群的大管家」
- 四种实现:
- Standalone:Spark 自带的集群管理器,简单独立,适合学习和小规模集群
- YARN:Hadoop 的资源管理器,企业最常用(和 Hadoop 共用集群资源)
- Mesos:Apache 的资源管理器,国内用得少
- Kubernetes:容器化资源管理,云原生趋势
② Driver Program(驱动程序)
- 作用:运行 main() 方法、创建 SparkContext 的进程,是应用的「指挥官」
- 核心职责:
- 把用户代码翻译成作业(Job)
- 把作业拆分成阶段(Stage)和任务(Task)
- 调度 Task 到 Executor 上执行
- 汇总执行结果
- 关键对象:
- SparkContext:Spark 应用的入口对象,所有 Spark 程序的第一步就是创建它
- DAGScheduler:负责 DAG 阶段划分
- TaskScheduler:负责任务分发
💡 通俗理解:Driver 就是「项目经理」,负责把大任务拆成小任务,分配给各个工人(Executor),最后汇总成果。
③ Worker Node(工作节点)
- 作用:集群中运行计算的物理机器(节点)
- 职责:
- 管理本节点的资源
- 接收 Cluster Manager 的指令
- 启动 Executor 进程
- 对应 Standalone 模式中的 Worker 进程
④ Executor(执行器)
- 作用:Worker Node 上为某个应用启动的进程,真正执行计算的「工人」
- 核心职责:
- 执行 Driver 分配的 Task(任务)
- 存储数据(RDD 缓存/持久化)
- 每个 Executor 有多个 CPU 核,可以并行跑多个 Task
- 重要参数:
executor-memory:每个 Executor 分配多少内存executor-cores:每个 Executor 分配多少 CPU 核
💡 通俗理解:Executor 就是「工人」,每个工人有几只手(cores)和多少力气(memory),同时能干几件活取决于手的数量。
⑤ Task(任务)
- 作用:Spark 中最小的执行单元,被发送到 Executor 上执行
- 每个 Task 对应 RDD 的一个分区
- 同一 Stage 内的 Task 是并行执行的
2.2 Spark 作业运行完整流程(面试必背)
以 Standalone 模式为例,一个 Spark 应用从提交到结束的完整流程:
第一步:提交应用
用户通过 spark-submit 提交应用,Driver 进程启动。
第二步:注册申请资源
- Driver 中的 SparkContext 向 Cluster Manager(Master)注册,申请运行 Executor 的资源
- Cluster Manager 查看 Worker 节点的资源情况
第三步:启动 Executor
- Cluster Manager 通知 Worker 节点启动 Executor 进程
- Worker 收到指令后,在本机启动 Executor 进程
- Executor 启动后反向向 Driver 注册,报告自己的资源情况
第四步:划分作业与阶段
- Driver 根据用户代码构建 RDD 依赖关系,形成 DAG(有向无环图)
- DAGScheduler 将 DAG 划分为多个 Stage(阶段),每个 Stage 包含一批 Task
- TaskScheduler 将 Task 分发到各个 Executor 上执行
第五步:执行任务
- Executor 收到 Task 后,启动线程执行
- 执行过程中,Driver 监控各个 Task 的状态
- 如果某个 Task 失败,Driver 会重新调度
第六步:返回结果 & 释放资源
- 所有 Task 执行完毕,结果返回给 Driver
- Driver 汇总结果,完成计算
- SparkContext 关闭,Cluster Manager 通知 Worker 释放 Executor 资源
流程图总结
用户提交应用 → Driver启动 → SparkContext向ClusterManager注册
↓
ClusterManager通知Worker启动Executor
↓
Executor向Driver反向注册
↓
Driver构建DAG → DAGScheduler划分Stage → TaskScheduler分发Task
↓
Executor执行Task → 结果返回Driver
↓
作业完成 → 释放资源⚠️ 高频考点:Driver 和 Executor 的区别?
- Driver 是「指挥官」,负责任务拆分和调度,跑在主节点/客户端
- Executor 是「工人」,负责真正执行计算,跑在工作节点
- 一个 Spark 应用只有一个 Driver,但可以有多个 Executor

YARN集群模式的作业运行流程

第三部分:RDD 核心概念与核心原理
3.1 什么是 RDD
RDD(Resilient Distributed Dataset):弹性分布式数据集,是 Spark 最基本、最核心的数据抽象。
三个关键词拆解
| 关键词 | 含义 |
|---|---|
| Resilient(弹性) | 容错,节点挂了可以根据血缘关系重新计算恢复,数据不丢 |
| Distributed(分布式) | 数据分布在多个节点上,可以并行计算 |
| Dataset(数据集) | 一个只读的数据集合,可以包含各种类型的数据 |

RDD 的五大核心特性(面试必背)
- 分区(Partition):RDD 由多个分区组成,每个分区是数据的一个子集,分区是计算的基本单位
- 计算函数(Compute):每个分区都有一个计算函数,对分区数据进行处理
- 依赖关系(Dependencies):RDD 之间有依赖关系(血缘 Lineage),记录了 RDD 是怎么来的
- 分区器(Partitioner):对于 Key-Value 类型的 RDD,可以指定分区器(Hash/Range)
- 首选位置(Preferred Location):每个分区的首选计算位置(移动计算不如移动数据,就近计算)
💡 通俗理解:RDD 就像「一份被切成很多块的大清单」,每一块(分区)分布在不同机器上,每块都知道自己是从哪来的(血缘),坏了可以照着记录重做。

3.2 RDD 算子分类:转换算子 vs 行动算子
RDD 的操作分为两大类:转换(Transformation) 和 行动(Action)。这是 Spark 最基础也最重要的概念。
① 转换算子(Transformation)—— 懒执行
特点:
- 不会立即执行,只是记录操作步骤
- 返回一个新的 RDD
- 像「列购物清单」,只写不买
常用转换算子:
| 算子 | 作用 | 示例 |
|---|---|---|
map(func) | 每个元素执行 func,返回新 RDD | rdd.map(x => x * 2) |
flatMap(func) | 先 map 再扁平化(一对多) | rdd.flatMap(_.split(" ")) |
filter(func) | 过滤,返回满足条件的元素 | rdd.filter(_ > 5) |
groupByKey() | 按 Key 分组 | pairRdd.groupByKey() |
reduceByKey(func) | 按 Key 聚合(先局部聚合再全局聚合) | pairRdd.reduceByKey(_+_) |
sortByKey() | 按 Key 排序 | pairRdd.sortByKey() |
join(other) | 两个 KV RDD 按 Key 关联 | rdd1.join(rdd2) |
union(other) | 两个 RDD 合并 | rdd1.union(rdd2) |
distinct() | 去重 | rdd.distinct() |
② 行动算子(Action)—— 触发执行
特点:
- 会真正触发计算,提交 Job
- 返回结果给 Driver 或写入外部存储
- 像「出门购物」,真正执行了
常用行动算子:
| 算子 | 作用 | 示例 |
|---|---|---|
collect() | 把所有数据收集到 Driver 端 | rdd.collect() |
count() | 返回元素个数 | rdd.count() |
first() | 返回第一个元素 | rdd.first() |
take(n) | 返回前 n 个元素 | rdd.take(10) |
reduce(func) | 聚合所有元素 | rdd.reduce(_+_) |
foreach(func) | 每个元素执行 func | rdd.foreach(println) |
saveAsTextFile(path) | 保存为文本文件 | rdd.saveAsTextFile("/out") |
countByKey() | 按 Key 统计数量 | pairRdd.countByKey() |
转换 vs 行动 快速判断技巧
- 返回值是 RDD → 大概率是转换算子
- 返回值是数字/数组/Unit(写入文件) → 大概率是行动算子
⚠️ 重要考点:为什么转换算子是懒执行?
- 好处1:可以对整个计算链做优化(DAG 调度),减少不必要的计算
- 好处2:节省资源,不用的时候不占内存和 CPU
- 类比:Excel 里写公式,改了数据不会立刻全表重算,而是等你按回车(行动算子)才计算

3.3 惰性求值与 DAG
什么是惰性求值(Lazy Evaluation)
Spark 遇到转换算子时,不会立即执行计算,只是记录下「这个 RDD 是怎么来的」(依赖关系)。直到遇到第一个行动算子,才真正触发计算。
举个例子理解
// 以下全是转换算子,不会触发计算,只是记录操作链
val rdd1 = sc.textFile("hdfs://...") // 读文件 → 记录
val rdd2 = rdd1.flatMap(_.split(" ")) // 切分 → 记录
val rdd3 = rdd2.map((_, 1)) // 映射 → 记录
val rdd4 = rdd3.reduceByKey(_+_) // 聚合 → 记录
// 遇到行动算子,才真正触发计算!
rdd4.saveAsTextFile("hdfs://.../output") // 行动算子 → 执行整个计算链DAG(有向无环图)
当行动算子触发时,Spark 会根据 RDD 的依赖关系,构建一个 DAG(Directed Acyclic Graph,有向无环图),然后由 DAGScheduler 进行阶段划分和优化。
转换与行动的完整流程
HDFS 文件
↓
textFile() ← 转换操作(记录)
↓
RDD A:文件内容(每行一个元素)
↓
flatMap() ← 转换操作(记录)
↓
RDD B:切分后的单词
↓
map() ← 转换操作(记录)
↓
RDD C:(单词, 1) 键值对
↓
reduceByKey() ← 转换操作(记录)
↓
RDD D:(单词, 总数)
↓
saveAsTextFile() ← 行动操作(触发执行!)
↓
HDFS 输出文件💡 关键理解:前面的 textFile、flatMap、map、reduceByKey 都是转换算子,只是记录操作步骤,不会真正执行。 直到最后遇到 saveAsTextFile(行动算子),才会从后往前回溯,构建 DAG,划分 Stage,然后真正开始计算。
💡 形象比喻:转换算子就像「搭多米诺骨牌」,一块接一块地摆好,但不会倒;行动算子就是「推倒第一块」,整个骨牌链才开始运转。
3.4 宽窄依赖(核心难点,面试必问)

RDD 之间的依赖关系分为两种:窄依赖(Narrow Dependency) 和 宽依赖(Wide Dependency / Shuffle Dependency)。
① 窄依赖(Narrow Dependency)
定义:父 RDD 的每个分区最多只被子 RDD 的一个分区使用(一对一 / 多对一)。
特点:
- 不需要 Shuffle(数据不需要在节点之间打乱重分区)
- 可以在同一个节点上流水线执行
- 容错成本低,只需要重算丢失的分区即可
常见窄依赖算子:map、filter、flatMap、union、mapPartitions 等
父RDD分区: [P1] [P2] [P3] [P4]
| | | |
↓ ↓ ↓ ↓
子RDD分区: [P1] [P2] [P3] [P4]
(一一对应,没有交叉)② 宽依赖(Wide Dependency / Shuffle Dependency)
定义:父 RDD 的每个分区被子 RDD 的多个分区使用(一对多),数据需要跨节点重新分发。
特点:
- 需要 Shuffle(数据洗牌,跨节点传输)
- 必须等父 RDD 所有分区计算完才能开始
- 是性能瓶颈点,也是 Stage 划分的依据
- 容错成本高,需要重算整个父 RDD
常见宽依赖算子:groupByKey、reduceByKey、join、distinct、repartition、sortByKey 等
父RDD分区: [P1] [P2] [P3]
/ | \ | / | \
/ | \ | / | \
↓ ↓ ↓↓ ↓ ↓
子RDD分区: [P1] [P2] [P3] [P4]
(交叉对应,数据洗牌)宽窄依赖对比表
| 对比项 | 窄依赖 | 宽依赖 |
|---|---|---|
| 分区关系 | 父分区 → 1个子分区 | 父分区 → 多个子分区 |
| 是否 Shuffle | 否 | 是 |
| 执行方式 | 流水线(pipeline) | 必须等待父阶段完成 |
| 性能 | 快 | 慢(IO+网络开销大) |
| Stage 划分 | 不划分 | 宽依赖就是 Stage 边界 |
| 容错成本 | 低(只重算丢失分区) | 高(重算整个父阶段) |
Stage(阶段)划分规则
DAGScheduler 划分 Stage 的核心规则:从后往前回溯,遇到宽依赖就切一刀,形成一个 Stage。
- 每个 Stage 包含一组可以流水线执行的窄依赖
- Stage 之间是宽依赖(Shuffle)
- 最后一个 Stage 叫 ResultStage,前面的叫 ShuffleMapStage
Task 的两种类型
在 Spark 中,一个作业会被拆分为多组任务,每组任务构成一个 Stage。Spark 中有两类任务:
| 任务类型 | 所属 Stage | 作用 | 输出 |
|---|---|---|---|
| ShuffleMapTask | ShuffleMapStage | 执行 Shuffle 前的计算,输出 Shuffle 所需的数据 | 中间结果(供下一个 Stage 使用) |
| ResultTask | ResultStage | 执行最终计算,输出最终结果 | 最终结果(返回 Driver 或写入外部存储) |
💡 理解:
- 每个 ShuffleMapStage 里的 Task 都是 ShuffleMapTask,负责把数据"洗牌"准备好
- 最后一个 ResultStage 里的 Task 是 ResultTask,负责产出最终结果
- 一个 Job 有几个 Stage,就有几批 Task 依次执行
💡 记忆口诀:「宽依赖切阶段,窄依赖流水线」

第四部分:Spark 部署模式详解
Spark 支持多种部署模式,不同模式的区别在于 Cluster Manager(集群管理器) 不同。
4.1 Local 模式(本地模式)
特点
- Spark 运行在单台机器上,不涉及集群
- 所有进程都在一个 JVM 里跑
- 不用启动 Master/Worker
用途
- 本地开发、调试代码
- 学习入门、测试
- 小数据量验证逻辑
启动方式
# 本地模式,使用所有CPU核
./bin/spark-shell --master local[*]
# 本地模式,指定2个CPU核
./bin/spark-shell --master local[2]4.2 Standalone 模式(独立集群模式)
特点
- Spark 自带的集群管理器,不依赖 Hadoop
- 有独立的 Master 和 Worker 进程
- 架构简单,部署方便
用途
- 学习 Spark 集群原理
- 纯 Spark 集群(不需要 Hadoop 生态)
- 小规模生产环境
核心进程
- Master:主节点进程,负责资源调度(对应 Standalone 的 Cluster Manager)
- Worker:工作节点进程,负责管理本节点资源、启动 Executor
- Driver:驱动程序(可以跑在客户端,也可以跑在集群里)
Driver Program 的位置(重要)
Standalone 模式下,Driver Program 既可以运行在主节点上,也可以运行在本地客户端 Client 上:
| 提交方式 | Driver 位置 | 说明 |
|---|---|---|
| spark-shell 交互式 | 主节点上 | 启动 spark-shell 时,Driver 跑在 Master 所在节点 |
| spark-submit 提交 | 本地客户端 | 用 spark-submit 提交 jar 包时,Driver 跑在提交的客户端机器上 |
| IDE 直接运行 | 本地客户端 | 在 Eclipse/IDEA 中 new SparkConf().setMaster("spark://master:7077") 运行时,Driver 跑在本地 |
Standalone 模式作业运行流程
1. 客户端提交应用 → Driver 启动
↓
2. Driver 向 Master 注册,申请运行 Executor 的资源
↓
3. Master 查看 Worker 节点资源,通知 Worker 启动 Executor
↓
4. Worker 启动 Executor 进程,Executor 向 Driver 反向注册
↓
5. Driver 构建 DAG,划分 Stage,将 Task 分发到 Executor 执行
↓
6. Executor 执行 Task,结果返回 Driver
↓
7. 作业完成,释放资源💡 验证方式:启动 spark-shell 后,访问
http://master:8080,可以在 Spark 监控界面看到对应的 Spark 应用程序信息。
4.3 YARN 模式(企业最常用,重点!)
特点
- 使用 Hadoop YARN 作为集群管理器
- Spark 应用作为 YARN 的一个作业运行
- 和 Hadoop 共用集群资源,资源利用率高
⚠️ 重要注意事项
在 YARN 模式中,不需要启动 Spark 独立集群!
- YARN 模式下,Spark 直接使用 YARN 的 ResourceManager 和 NodeManager 来管理资源
- 不需要启动 Spark 的 Master 和 Worker 进程
- 因此
http://master:8080(Spark Master 的 Web UI)是访问不了的 - 监控界面看 YARN 的 Web UI:
http://master:8088
💡 常见误区:很多初学者跑 YARN 模式时还去启动 Spark 集群,其实完全不需要。YARN 模式下 Spark 只是 YARN 的一个"客户端",资源全交给 YARN 管。
为什么企业都用 YARN?
- 资源统一管理:Hadoop、Hive、Spark 共用一套 YARN 集群
- 资源调度更成熟:YARN 的队列、资源隔离机制更完善
- 运维成本低:不用维护两套集群
YARN 模式分两种:Client 和 Cluster
① YARN Client 模式
- Driver 跑在提交作业的客户端机器上
- ApplicationMaster 只负责向 YARN 申请资源
- 客户端退出,作业就挂了
② YARN Cluster 模式
- Driver 跑在 YARN 集群的 ApplicationMaster 中
- 提交作业后客户端可以断开,不影响作业运行
- 生产环境推荐使用
对比表
| 对比项 | YARN Client | YARN Cluster |
|---|---|---|
| Driver 位置 | 客户端机器 | YARN 集群的 AM 中 |
| 客户端断开 | 作业终止 | 作业继续运行 |
| 适用场景 | 调试、交互式(spark-shell) | 生产环境、后台作业 |
| 日志查看 | 直接在客户端看 | 需从 YARN 日志中查看 |
| ApplicationMaster 职责 | 只负责申请资源 | 负责申请资源 + 监督作业运行 |
YARN Cluster 模式作业运行流程(6步)
1. 客户端提交应用程序
↓
2. ResourceManager 接收请求,在某个 NodeManager 上启动 ApplicationMaster
↓
3. ApplicationMaster 中启动 Driver Program
↓
4. ApplicationMaster 向 ResourceManager 申请资源(Executor)
↓
5. ResourceManager 分配资源,在各 NodeManager 上启动 Container + Executor
↓
6. Driver 将 Task 分发到各 Executor 上执行,Executor 向 Driver 注册汇报⚠️ 重要注意:
spark-shell只能用 YARN Client 模式,不能用 Cluster 模式! 因为 spark-shell 是交互式的,需要 Driver 在本地和用户交互。
4.4 Mesos 模式 & Kubernetes 模式(了解)
Mesos 模式
- Apache Mesos 作为资源管理器
- 国内使用较少,了解即可
Kubernetes 模式
- 使用 K8s 作为资源管理器
- 容器化部署,弹性伸缩方便
- 云原生趋势,未来会越来越多
- 目前生产环境用得还不算特别普遍
4.5 四种部署模式对比总结
| 模式 | Cluster Manager | 适用场景 | 学习优先级 |
|---|---|---|---|
| Local | 无(本地) | 开发调试、入门学习 | ⭐⭐⭐⭐⭐ 第一个学 |
| Standalone | Spark 自带 | 学习集群原理、纯Spark集群 | ⭐⭐⭐⭐ 重点学 |
| YARN | Hadoop YARN | 企业生产环境(最主流) | ⭐⭐⭐⭐⭐ 必须掌握 |
| Mesos | Apache Mesos | 国内少用 | ⭐ 了解 |
| K8s | Kubernetes | 云原生、容器化 | ⭐⭐ 了解趋势 |
第五部分:Spark 环境搭建实操(重点)
以下操作基于 Spark 3.5.1 + Hadoop 3.3.6 + JDK 1.8,集群节点:master、slave1、slave2
5.1 前置准备(必须先搞定)
① 基础环境软件清单
在正式搭建 Spark 环境之前,需要准备好以下基础虚拟机环境:
| 相关软件 | 安装包 / 版本 | 说明 |
|---|---|---|
| 操作系统 | Rocky-9.6-x86_64-dvd.iso | Linux 操作系统 |
| 虚拟化工具 | VMware-workstation-full-17.6.0 | 虚拟机软件(如果用虚拟机) |
| SSH 连接工具 | MobaXterm_Portable_v22.1.zip | 远程连接 Linux 服务器 |
| JDK | jdk-8u461-linux-x64.tar.gz | Java 运行环境(必须) |
| Hadoop | hadoop-3.3.6.tar.gz | Hadoop 集群(YARN + HDFS) |
| MySQL | mysql-8.0.30 安装包 | 元数据库(Hive 用) |
| Hive | apache-hive-3.1.3-bin.tar.gz | 数据仓库(可选,后续用) |
② 基础环境要求
- JDK 1.8+(已安装,路径:
/usr/local/jdk1.8.0_461) - Hadoop 集群(已搭建,路径:
/usr/local/hadoop-3.3.6) - Scala(可选,Spark 自带 Scala 运行环境)
- 三台 Linux 服务器,主机名:master、slave1、slave2
- 主机名映射(/etc/hosts 已配置)
- SSH 免密登录(master 能免密登录所有节点)
- 防火墙关闭或开放对应端口
② Spark 安装包说明
- 版本:
spark-3.5.1-bin-hadoop3-scala2.13.tgz - 命名解读:
3.5.1:Spark 版本号bin-hadoop3:预编译适配 Hadoop 3.xscala2.13:使用 Scala 2.13 版本编译
③ 安装包位置
- 安装包存放:
/opt/apps/spark-3.5.1-bin-hadoop3-scala2.13.tgz - 安装目标路径:
/usr/local/
5.2 任务一:Spark 单机 / Local 模式搭建
最简单的模式,解压配置环境变量就能用,适合快速入门
步骤1:解压安装包
# 解压到 /usr/local 目录
tar -zxf /opt/apps/spark-3.5.1-bin-hadoop3-scala2.13.tgz -C /usr/local/解压后目录:/usr/local/spark-3.5.1-bin-hadoop3-scala2.13/
步骤2:配置环境变量
编辑 /etc/profile:
vi /etc/profile在文件末尾添加:
# SPARK_HOME
export SPARK_HOME=/usr/local/spark-3.5.1-bin-hadoop3-scala2.13
export PATH=$PATH:$SPARK_HOME/bin使配置生效:
source /etc/profile步骤3:验证 Local 模式
启动 spark-shell(默认就是 Local 模式):
cd $SPARK_HOME
./bin/spark-shell看到 scala> 提示符就是成功了。退出用 :quit。
5.3 任务二:Spark 单机伪分布式搭建
伪分布式:只有一台机器,但模拟了 Master + Worker 的集群架构
步骤1:配置 spark-env.sh
进入配置目录,从模板复制:
cd /usr/local/spark-3.5.1-bin-hadoop3-scala2.13/conf/
cp spark-env.sh.template spark-env.sh编辑 spark-env.sh:
vi spark-env.sh添加以下内容:
export JAVA_HOME=/usr/local/jdk1.8.0_461
export HADOOP_HOME=/usr/local/hadoop-3.3.6
export HADOOP_CONF_DIR=/usr/local/hadoop-3.3.6/etc/hadoop
export SPARK_MASTER_IP=master
export SPARK_LOCAL_IP=master💡 配置说明:
JAVA_HOME:JDK 路径,必须配HADOOP_HOME&HADOOP_CONF_DIR:如果要读 HDFS 数据或跑 YARN,必须配SPARK_MASTER_IP:Master 节点主机名SPARK_LOCAL_IP:本机IP/主机名
步骤2:启动 Spark 集群
cd $SPARK_HOME/sbin/
./start-all.sh步骤3:验证进程
jps应该看到两个进程:
- Master:主节点进程
- Worker:工作节点进程
步骤4:Web UI 查看
浏览器访问:http://master:8080(Master 的 Web UI)
- 可以看到集群状态、Worker 数量、资源情况
步骤5:运行测试案例——SparkPi
cd $SPARK_HOME/bin/
./run-example SparkPi 2说明:SparkPi 是 Spark 自带的示例程序,用蒙特卡洛方法计算圆周率 Pi 的值,参数
2表示用 2 个分区。
如果输出结果中包含 Pi is roughly 3.14... 就说明伪分布式搭建成功!
5.4 任务三:Spark 完全分布式集群搭建(核心重点)
三节点集群:master(主)、slave1(从)、slave2(从) 这是本章的重点实验,也是面试常考的实操题
整体规划
| 节点 | 角色 | 进程 |
|---|---|---|
| master | 主节点 | Master、Worker、HistoryServer |
| slave1 | 从节点 | Worker |
| slave2 | 从节点 | Worker |

步骤1:配置 spark-env.sh(在 master 上操作)
进入配置目录(如果还没复制模板):
cd /usr/local/spark-3.5.1-bin-hadoop3-scala2.13/conf/
cp spark-env.sh.template spark-env.sh编辑 spark-env.sh:
vi spark-env.sh完整配置内容:
export JAVA_HOME=/usr/local/jdk1.8.0_461
export HADOOP_HOME=/usr/local/hadoop-3.3.6
export HADOOP_CONF_DIR=/usr/local/hadoop-3.3.6/etc/hadoop
export LD_LIBRARY_PATH=$HADOOP_HOME/lib/native
export SPARK_MASTER_IP=master
export SPARK_MASTER_PORT=7077
export SPARK_WORKER_MEMORY=512m
export SPARK_WORKER_CORES=1
export SPARK_EXECUTOR_MEMORY=512m
export SPARK_EXECUTOR_CORES=1
export SPARK_WORKER_INSTANCES=1💡 配置详解:
配置项 含义 说明 JAVA_HOMEJDK 路径 必须配置,所有 Java 程序都需要 HADOOP_HOMEHadoop 安装路径 读写 HDFS、跑 YARN 时需要 HADOOP_CONF_DIRHadoop 配置目录 告诉 Spark 去哪找 Hadoop 配置 LD_LIBRARY_PATHHadoop 本地库路径 支持压缩、本地IO优化 SPARK_MASTER_IPMaster 主机名 指定 Master 在哪台机器 SPARK_MASTER_PORTMaster 端口 默认 7077,Spark 应用提交的端口 SPARK_WORKER_MEMORYWorker 可用内存 每个 Worker 节点能给 Spark 用多少内存 SPARK_WORKER_CORESWorker 可用 CPU 核数 每个 Worker 节点能给 Spark 用多少核 SPARK_EXECUTOR_MEMORY每个 Executor 内存 每个 Executor 进程分配多少内存 SPARK_EXECUTOR_CORES每个 Executor 核数 每个 Executor 进程分配多少 CPU 核 SPARK_WORKER_INSTANCES每台机器 Worker 实例数 一般1个,特殊情况可以多开
⚠️ 注意:教学环境内存有限,所以配 512m。生产环境一般配几 GB 到几十 GB。
步骤2:配置 workers 文件(指定从节点)
workers 文件用来指定哪些节点是 Worker 节点(Spark 2.x 及以前叫 slaves 文件)。
cd $SPARK_HOME/conf/
cp workers.template workers
vi workers添加以下内容(每行一个主机名):
master
slave1
slave2说明:master 也作为 Worker 节点参与计算(教学环境资源有限)。生产环境一般 Master 不做 Worker,专门负责调度。
步骤3:配置 spark-defaults.conf(默认参数配置)
这个文件配置 Spark 应用的默认参数,每次提交应用不用每次都写参数。
cd $SPARK_HOME/conf/
cp spark-defaults.conf.template spark-defaults.conf
vi spark-defaults.conf添加以下内容:
spark.master spark://master:7077
spark.eventLog.enabled true
spark.eventLog.dir hdfs://master:8020/spark-logs
spark.history.fs.logDirectory hdfs://master:8020/spark-logs💡 配置详解:
配置项 含义 说明 spark.master默认提交的集群地址 设为 Standalone 集群地址,spark-shell 不用每次写 --master spark.eventLog.enabled是否开启事件日志 true 开启,记录应用运行日志 spark.eventLog.dir事件日志存储路径 存在 HDFS 上,HistoryServer 才能读取 spark.history.fs.logDirectoryHistoryServer 日志目录 HistoryServer 从这个目录读日志展示历史记录
步骤4:将 Spark 安装目录远程复制到其他节点
在 master 上操作,把整个 Spark 目录复制到 slave1 和 slave2:
scp -r /usr/local/spark-3.5.1-bin-hadoop3-scala2.13/ slave1:/usr/local/
scp -r /usr/local/spark-3.5.1-bin-hadoop3-scala2.13/ slave2:/usr/local/⚠️ 前提:master 到 slave1、slave2 已经配置了 SSH 免密登录。 如果没配置免密,每次 scp 都要输入密码。
步骤5:同步环境变量配置
把 master 的 /etc/profile 同步到其他节点(或者分别在每个节点配置):
scp /etc/profile slave1:/etc/
scp /etc/profile slave2:/etc/然后在每个节点执行 source /etc/profile 使配置生效。
步骤6:启动 Hadoop 集群(必须先启动!)
因为我们把日志存在 HDFS 上,而且后续要跑 YARN 模式,所以必须先启动 Hadoop。
# 启动 Hadoop 集群
$HADOOP_HOME/sbin/start-all.sh
# 启动 MapReduce 历史服务器
$HADOOP_HOME/sbin/mr-jobhistory-daemon.sh start historyserver步骤7:在 HDFS 上创建 spark-logs 目录
HistoryServer 需要从 HDFS 读取日志,所以要先创建目录:
hdfs dfs -mkdir /spark-logs步骤8:启动 Spark 集群
# 启动 Master + 所有 Worker
$SPARK_HOME/sbin/start-all.sh
# 启动历史服务器
$SPARK_HOME/sbin/start-history-server.sh步骤9:验证集群
方法一:查看进程
在 master 上执行 jps,应该有:
- Master
- Worker
- HistoryServer
在 slave1、slave2 上执行 jps,应该有:
- Worker
方法二:Web UI 查看
Master Web UI(集群实时监控):
http://master:8080- 作用:监控集群的实时状态
- 可以查看:Worker 节点列表、集群总资源(内存、CPU核数)、正在运行的应用、已完成的应用
- 只有 Standalone 模式有这个界面,YARN 模式没有
HistoryServer Web UI(历史作业监控):
http://master:18080- 作用:记录和查看所有作业的历史信息
- 可以查看:已运行完成的作业、正在运行的作业、具体的作业日志链接
- 需要配置 spark.eventLog.enabled = true 并启动 HistoryServer 才能用
方法三:运行测试程序
# 运行 SparkPi 示例(用 2 个分区)
$SPARK_HOME/bin/run-example SparkPi 2如果能正常输出 Pi 的近似值,说明完全分布式集群搭建成功!
5.5 集群启停命令汇总
启动命令
# 启动所有(Master + 所有 Worker)
$SPARK_HOME/sbin/start-all.sh
# 只启动 Master
$SPARK_HOME/sbin/start-master.sh
# 只启动 Worker(在从节点执行)
$SPARK_HOME/sbin/start-worker.sh spark://master:7077
# 启动历史服务器
$SPARK_HOME/sbin/start-history-server.sh停止命令
# 停止所有
$SPARK_HOME/sbin/stop-all.sh
# 只停止 Master
$SPARK_HOME/sbin/stop-master.sh
# 只停止 Worker
$SPARK_HOME/sbin/stop-worker.sh
# 停止历史服务器
$SPARK_HOME/sbin/stop-history-server.sh5.6 spark-shell 常用启动方式
① Local 模式(默认)
./bin/spark-shell
# 等价于
./bin/spark-shell --master local[*]② 指定资源启动
./bin/spark-shell --executor-memory 512m --total-executor-cores 3说明:
--executor-memory 512m:每个 Executor 512MB 内存--total-executor-cores 3:总共用 3 个 CPU 核
③ Standalone 模式
./bin/spark-shell --master spark://master:7077④ YARN Client 模式
./bin/spark-shell --master yarn --deploy-mode client⚠️ 重要:spark-shell 不能用 YARN Cluster 模式! 因为 spark-shell 是交互式的,需要 Driver 在本地。 以下命令会失败:
bash# ❌ 错误:spark-shell 不能用 cluster 模式 ./bin/spark-shell --master yarn --deploy-mode cluster
第六部分:Spark 初体验——WordCount & SparkPi
6.1 WordCount(词频统计)—— Spark 的 HelloWorld
WordCount 是大数据领域的「HelloWorld」,每个框架入门必写。
Scala 版本(spark-shell 中执行)
// 一行搞定 WordCount
sc.textFile("/user/root/test.txt")
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_ + _)
.saveAsTextFile("/user/root/output")逐行拆解
| 代码 | 含义 | 算子类型 |
|---|---|---|
sc.textFile("/user/root/test.txt") | 读取 HDFS 文件,每一行是一个元素,返回 RDD[String] | 转换 |
.flatMap(_.split(" ")) | 每行按空格切分成单词,再扁平化 | 转换 |
.map((_, 1)) | 每个单词变成 (单词, 1) 的键值对 | 转换 |
.reduceByKey(_ + _) | 按单词分组,把 1 累加起来 | 转换(宽依赖) |
.saveAsTextFile("/user/root/output") | 结果保存到 HDFS | 行动(触发计算) |
执行流程说明
- 前四步都是转换算子,不会触发计算,只是构建 RDD 依赖链
- 最后一步
saveAsTextFile是行动算子,触发整个 Job 执行 reduceByKey是宽依赖,会触发 Shuffle,是 Stage 划分的边界
6.2 SparkPi 案例
Spark 自带的示例程序,用蒙特卡洛算法计算圆周率。
运行方式
cd $SPARK_HOME/bin/
./run-example SparkPi 2参数 2 表示分区数(并行度)。
原理简述(了解即可)
- 在一个正方形内画一个内切圆
- 随机向正方形内扔点,统计落在圆内的点的比例
- 比例 ≈ 圆面积 / 正方形面积 = π/4
- 所以 π ≈ 4 × 比例
- 分区数越多,并行度越高,计算越快,结果也越精确
第七部分:常见问题与排错指南
这部分是实操中最容易踩的坑,实习面试也常考排错思路
7.1 启动类问题
问题1:start-all.sh 后 Master 或 Worker 进程没起来
排查思路:
- 看日志:
$SPARK_HOME/logs/目录下找对应的日志文件 - 检查 JAVA_HOME 是否配置正确(最常见原因)
- 检查主机名是否正确,/etc/hosts 是否配置
- 检查端口是否被占用(Master 默认 8080、7077)
问题2:Worker 注册不上 Master
排查思路:
- 检查
spark-env.sh中SPARK_MASTER_IP是否正确 - 检查 Worker 节点能否 ping 通 Master
- 检查防火墙是否关闭
- 检查 Master 的 7077 端口是否开放
问题3:启动 HistoryServer 报错
排查思路:
- 检查 Hadoop 是否启动(日志在 HDFS 上)
- 检查
/spark-logs目录是否已创建 - 检查
spark-defaults.conf中 HDFS 路径是否正确 - 检查 HDFS 的地址和端口(默认 8020,有的是 9000)
7.2 运行类问题
问题4:spark-shell 启动报错:找不到 Hadoop 配置
原因:没有配置 HADOOP_CONF_DIR
解决:在 spark-env.sh 中添加:
export HADOOP_HOME=/usr/local/hadoop-3.3.6
export HADOOP_CONF_DIR=/usr/local/hadoop-3.3.6/etc/hadoop问题5:YARN 模式提交报错:找不到 YARN 配置
原因:Spark 不知道 YARN 在哪
解决:确保 HADOOP_CONF_DIR 配置正确,Spark 会从这个目录读取 yarn-site.xml
问题6:spark-shell 用 YARN cluster 模式启动失败
原因:spark-shell 是交互式的,只能用 client 模式
解决:改用 --deploy-mode client
问题7:内存不足,Executor 启动失败
现象:作业提交后 Executor 一直处于 FAILED 状态
原因:配置的内存超过了 Worker/YARN 可用资源
解决:调小 spark.executor.memory 和 spark.driver.memory
7.3 配置类问题
问题8:scp 远程复制需要输入密码
原因:SSH 免密登录没配置好
解决:配置 SSH 免密登录
# 生成密钥(一路回车)
ssh-keygen -t rsa
# 把公钥复制到目标节点
ssh-copy-id root@slave1
ssh-copy-id root@slave2问题9:环境变量不生效
原因:只改了 /etc/profile 但没 source,或者用户不一样
解决:
source /etc/profile如果是普通用户,还要检查 ~/.bashrc 或 ~/.bash_profile
问题10:Web UI 访问不了
排查思路:
- 检查进程是否启动(jps)
- 检查防火墙是否关闭
- 检查端口号是否正确(Master 8080,HistoryServer 18080)
- 检查浏览器地址是否正确(主机名能不能解析)
7.4 排错通用思路(面试常问)
- 看日志:第一时间去
$SPARK_HOME/logs/看日志,报错信息都在里面 - 看进程:
jps看该有的进程在不在 - 看配置:检查配置文件路径、主机名、端口有没有写错
- 看网络:ping 一下,看网络通不通
- 看权限:文件/目录权限够不够
- 看资源:内存、CPU 够不够
💡 排错口诀:「日志先行,进程跟上,配置核对,网络权限,最后资源」
第八部分:实习 / 面试高频考点
针对大专生实习面试,整理本章最常考的知识点,按频率排序
8.1 概念类(高频)
Q1:Spark 和 MapReduce 的区别?
参考 1.2 节对比表,重点说:速度(内存vs磁盘)、编程模型(丰富API vs 只有MapReduce)、通用性(一套引擎多场景 vs 只能批处理)
Q2:Spark 为什么比 MapReduce 快?
三个核心原因:① 内存计算 ② DAG调度优化 ③ 高效的Shuffle机制
Q3:什么是 RDD?RDD 的五大特性?
弹性分布式数据集。五大特性:分区、计算函数、依赖关系、分区器、首选位置
Q4:转换算子和行动算子的区别?举几个例子
转换:懒执行,返回RDD,如 map/filter/flatMap/reduceByKey 行动:触发计算,返回结果或写入存储,如 collect/count/saveAsTextFile/reduce
Q5:什么是惰性求值?有什么好处?
转换算子不立即执行,遇到行动算子才执行。好处:可以做DAG优化、节省资源
Q6:宽窄依赖的区别?哪些算子是宽依赖?
窄依赖:父分区→1个子分区,不Shuffle,如 map/filter 宽依赖:父分区→多个子分区,要Shuffle,如 groupByKey/reduceByKey/join/distinct Stage 划分就是按宽依赖来切的
Q7:Spark 的运行架构?核心组件有哪些?
主从架构。核心组件:Cluster Manager、Driver、Worker、Executor、Task
Q8:Spark 有哪些部署模式?
Local、Standalone、YARN、Mesos、Kubernetes
Q9:YARN client 和 cluster 模式的区别?
Driver 位置不同:client 模式 Driver 在客户端,cluster 模式 Driver 在 YARN 的 AM 里 适用场景:client 适合调试交互,cluster 适合生产环境
Q10:Spark 生态圈有哪些组件?
Spark Core、Spark SQL、Spark Streaming/Structured Streaming、MLlib、GraphX
8.2 实操类(高频)
Q11:怎么搭建 Spark 完全分布式集群?步骤是什么?
参考 5.4 节,按步骤说: ① 解压安装包 ② 配置 spark-env.sh ③ 配置 workers ④ 配置 spark-defaults.conf ⑤ 远程复制到其他节点 ⑥ 启动 Hadoop ⑦ 创建 HDFS 日志目录 ⑧ 启动 Spark 集群
Q12:spark-env.sh 里一般配什么?
JAVA_HOME、HADOOP_HOME、HADOOP_CONF_DIR、SPARK_MASTER_IP、内存和核数参数
Q13:workers 文件是干嘛的?
指定哪些节点是 Worker 节点,每行一个主机名
Q14:Spark 历史服务器怎么配置?
spark-defaults.conf 里配置:
- spark.eventLog.enabled = true
- spark.eventLog.dir = hdfs://.../spark-logs
- spark.history.fs.logDirectory = hdfs://.../spark-logs 然后 start-history-server.sh 启动
Q15:spark-shell 能不能用 YARN cluster 模式?为什么?
不能。因为 spark-shell 是交互式的,需要 Driver 在本地和用户交互,只能用 client 模式
8.3 原理类(中高频)
Q16:Spark 作业的运行流程?
参考 2.2 节完整流程:提交应用 → Driver启动 → 注册申请资源 → 启动Executor → 划分Stage → 分发Task → 执行 → 返回结果 → 释放资源
Q17:DAGScheduler 和 TaskScheduler 的区别?
DAGScheduler:负责 DAG 阶段划分,把 Job 切成多个 Stage TaskScheduler:负责任务分发,把 Task 发到 Executor 上执行
Q18:Stage 是怎么划分的?
从后往前回溯 DAG,遇到宽依赖就切一刀,形成一个 Stage 窄依赖可以流水线执行,放在同一个 Stage 里
Q19:Spark 的容错机制?
RDD 血缘(Lineage):记录 RDD 的依赖关系,数据丢了根据血缘重新计算即可 比副本容错更节省资源
8.4 对比类(中频)
Q20:Spark SQL 和 Hive 的区别?
- Spark SQL 计算引擎是 Spark,Hive 默认是 MapReduce(也可以换 Spark 引擎)
- Spark SQL 速度更快
- Hive 更偏向数据仓库管理,Spark SQL 更偏向计算
- Spark on Hive 可以直接读 Hive 表
Q21:RDD、DataFrame、DataSet 的区别?
- RDD:最底层,类型安全,API 最灵活,但优化少(不了解 Spark SQL 优化器)
- DataFrame:有 Schema(表结构),有列名和类型,API 更像 SQL,优化多
- DataSet:强类型的 DataFrame,兼具 RDD 的类型安全和 DataFrame 的优化
- 性能:DataFrame/DataSet > RDD(因为有 Catalyst 优化器)
第九部分:项目小结
本项目是 Spark 学习的入门项目,主要内容包括:
- Spark 简介:了解 Spark 的特点、生态圈和应用场景,认识 Spark 是什么、能做什么
- Spark 运行架构与原理:
- Spark 主从架构与核心组件(Driver、Worker、Executor、Task)
- Spark 作业运行完整流程
- 核心数据集 RDD 的概念与操作(转换算子 vs 行动算子)
- 核心原理:宽窄依赖、Stage 划分、惰性求值、DAG
- Spark 环境搭建:
- 单机模式(Local):解压配置即可,快速入门
- 单机伪分布式:一台机器模拟集群,学习架构
- 完全分布式:三节点真实集群,生产环境标准
- 配置文件:spark-env.sh、workers、spark-defaults.conf
💡 本章学习目标达成检查:
- ✅ 能说出 Spark 的 5~6 个核心特点
- ✅ 能画出 Spark 运行架构图,说出各组件作用
- ✅ 能区分转换算子和行动算子,各举 3 个例子
- ✅ 能解释什么是宽窄依赖,以及 Stage 怎么划分
- ✅ 能独立搭建 Spark 完全分布式集群
- ✅ 能说出 4 种部署模式的区别,以及 YARN client 和 cluster 的区别
附录:选择题解析
对应教材/课件的10道选择题,逐一解析:
1、答案:D 解析:Spark架构中的组件包括 Driver Program、SparkContext、Cluster Manager、Worker Node 等。ResourceManager 是 Hadoop YARN 中的组件,不是 Spark 架构的组件。
2、答案:D 解析:相比于 Hadoop,Spark 继承了 MapReduce 分布式计算的优点,并改进了 MapReduce 的明显缺陷(如基于磁盘、速度慢、编程模型单一等)。
3、答案:D 解析:Spark 的运行模式包括 Standalone、YARN、Mesos 和 Kubernetes 共 4 种。HDFS 是 Hadoop 集群中的分布式文件系统,不是 Spark 的运行模式。
4、答案:C 解析:在 Spark 中:
- Spark MLlib → 机器学习场景
- Spark SQL → SQL 查询
- Spark Streaming → 实时数据流式计算
- Spark GraphX → 图计算应用
5、答案:B 解析:行动操作主要指将 RDD 存储至硬盘中或触发转换操作执行的操作(Action 触发 Job 执行)。
6、答案:A 解析:「AMP」分别指算法(Algorithm)、机器(Machine)、人(People)。AMP Lab 是加州大学伯克利分校的实验室,Spark 就诞生于此。
7、答案:B 解析:Spark RDD 常用的转换操作有 map()、filter()、flatMap()、union()、groupByKey()、reduceByKey() 等。转换算子返回新 RDD,懒执行。
8、答案:A 解析:Spark RDD 常用的行动操作有 reduce()、collect()、count()、first()、take()、saveAsTextFile()、foreach() 等。行动算子触发计算。
9、答案:C 解析:
- /etc/profile → 配置本地系统环境变量
- spark-env.sh → 配置 Spark 集群运行时的环境变量
- workers → 配置 Spark 集群的工作节点
- spark-defaults.conf → 配置 Spark 应用程序的默认参数
10、答案:C 解析:Spark 集群启动后的进程包括 Master(主节点)、Worker(工作节点)、HistoryServer(历史日志服务)。JobHistoryServer 是 Hadoop 集群的 MapReduce 作业的历史日志服务进程,不是 Spark 的。
笔记版本:V1.0 对应教材:《Spark大数据技术与应用(第3版)》人民邮电出版社 最后更新:2026年8月