前言
刚接触大数据的时候,我最先学的是Hadoop相关计算,早期只用MapReduce写WordCount跑任务要等半天,多轮迭代场景磁盘IO直接卡死集群。后来才知道,Spark就是为了解决MR磁盘读写慢的痛点而生。
本文完整整合Spark全套学习资料,从Spark基础、RDD核心、Spark SQL、Spark Streaming、MLlib&GraphX由浅入深讲解,配套Mermaid流程图、可运行PySpark代码、对比表格、原理示意图,零基础也能看懂,适合大数据初学者、面试复习、开发查阅。
一、Hadoop回顾:MapReduce的致命短板
1.1 Hadoop完整生态架构
Hadoop完整生态由三大核心组件共同组成,三者配合才算一套完整大数据平台:
- HDFS:分布式文件存储,负责海量数据持久化;
- YARN:资源调度框架,统一管理集群CPU、内存资源;
- MapReduce :第一代分布式批处理计算框架,仅负责计算逻辑。
#mermaid-svg-nbS36xN62B3epThs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nbS36xN62B3epThs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nbS36xN62B3epThs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nbS36xN62B3epThs .error-icon{fill:#552222;}#mermaid-svg-nbS36xN62B3epThs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nbS36xN62B3epThs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nbS36xN62B3epThs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nbS36xN62B3epThs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nbS36xN62B3epThs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nbS36xN62B3epThs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nbS36xN62B3epThs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nbS36xN62B3epThs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nbS36xN62B3epThs .marker.cross{stroke:#333333;}#mermaid-svg-nbS36xN62B3epThs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nbS36xN62B3epThs p{margin:0;}#mermaid-svg-nbS36xN62B3epThs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nbS36xN62B3epThs .cluster-label text{fill:#333;}#mermaid-svg-nbS36xN62B3epThs .cluster-label span{color:#333;}#mermaid-svg-nbS36xN62B3epThs .cluster-label span p{background-color:transparent;}#mermaid-svg-nbS36xN62B3epThs .label text,#mermaid-svg-nbS36xN62B3epThs span{fill:#333;color:#333;}#mermaid-svg-nbS36xN62B3epThs .node rect,#mermaid-svg-nbS36xN62B3epThs .node circle,#mermaid-svg-nbS36xN62B3epThs .node ellipse,#mermaid-svg-nbS36xN62B3epThs .node polygon,#mermaid-svg-nbS36xN62B3epThs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nbS36xN62B3epThs .rough-node .label text,#mermaid-svg-nbS36xN62B3epThs .node .label text,#mermaid-svg-nbS36xN62B3epThs .image-shape .label,#mermaid-svg-nbS36xN62B3epThs .icon-shape .label{text-anchor:middle;}#mermaid-svg-nbS36xN62B3epThs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nbS36xN62B3epThs .rough-node .label,#mermaid-svg-nbS36xN62B3epThs .node .label,#mermaid-svg-nbS36xN62B3epThs .image-shape .label,#mermaid-svg-nbS36xN62B3epThs .icon-shape .label{text-align:center;}#mermaid-svg-nbS36xN62B3epThs .node.clickable{cursor:pointer;}#mermaid-svg-nbS36xN62B3epThs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nbS36xN62B3epThs .arrowheadPath{fill:#333333;}#mermaid-svg-nbS36xN62B3epThs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nbS36xN62B3epThs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nbS36xN62B3epThs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nbS36xN62B3epThs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nbS36xN62B3epThs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nbS36xN62B3epThs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nbS36xN62B3epThs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nbS36xN62B3epThs .cluster text{fill:#333;}#mermaid-svg-nbS36xN62B3epThs .cluster span{color:#333;}#mermaid-svg-nbS36xN62B3epThs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nbS36xN62B3epThs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nbS36xN62B3epThs rect.text{fill:none;stroke-width:0;}#mermaid-svg-nbS36xN62B3epThs .icon-shape,#mermaid-svg-nbS36xN62B3epThs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nbS36xN62B3epThs .icon-shape p,#mermaid-svg-nbS36xN62B3epThs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nbS36xN62B3epThs .icon-shape .label rect,#mermaid-svg-nbS36xN62B3epThs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nbS36xN62B3epThs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nbS36xN62B3epThs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nbS36xN62B3epThs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端提交任务
YARN ResourceManager 资源总管
NodeManager 节点1
NodeManager 节点2
Map阶段任务
本地磁盘/ HDFS 落盘中间结果
Reduce阶段任务
Map阶段任务
Reduce阶段任务
1.2 MapReduce核心缺陷
MapReduce每一轮计算中间结果强制写入磁盘,举个WordCount案例:
- Map:读取文件,拆分单词,输出
(word,1)写入本地磁盘; - Shuffle:读取磁盘数据,按key分组;
- Reduce:聚合相同单词计数,再次落地磁盘。
多轮迭代计算(机器学习、多层聚合)会反复读写磁盘,IO开销爆炸,性能极差,这就是Spark诞生的核心背景。
二、Apache Spark 完整介绍
2.1 Spark起源与定义
2009年加州大学伯克利分校AMPLab推出,核心论文《Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing》,提出RDD弹性分布式数据集。
官方定义:Apache Spark是用于大规模数据处理的统一内存分析引擎,基于内存做分布式并行计算,中间结果优先存内存,内存不足再溢写到磁盘,大幅降低磁盘IO。
2.2 Spark四大核心特点
1)快:内存计算 + DAG有向无环图调度
- 内存中运算速度比MapReduce快100倍;磁盘运算快10倍;
- MapReduce线性分阶段执行,Spark通过DAG合并计算阶段,减少Shuffle与磁盘读写。
#mermaid-svg-tjnHydNk5QjIP3qv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tjnHydNk5QjIP3qv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tjnHydNk5QjIP3qv .error-icon{fill:#552222;}#mermaid-svg-tjnHydNk5QjIP3qv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tjnHydNk5QjIP3qv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tjnHydNk5QjIP3qv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tjnHydNk5QjIP3qv .marker.cross{stroke:#333333;}#mermaid-svg-tjnHydNk5QjIP3qv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tjnHydNk5QjIP3qv p{margin:0;}#mermaid-svg-tjnHydNk5QjIP3qv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tjnHydNk5QjIP3qv .cluster-label text{fill:#333;}#mermaid-svg-tjnHydNk5QjIP3qv .cluster-label span{color:#333;}#mermaid-svg-tjnHydNk5QjIP3qv .cluster-label span p{background-color:transparent;}#mermaid-svg-tjnHydNk5QjIP3qv .label text,#mermaid-svg-tjnHydNk5QjIP3qv span{fill:#333;color:#333;}#mermaid-svg-tjnHydNk5QjIP3qv .node rect,#mermaid-svg-tjnHydNk5QjIP3qv .node circle,#mermaid-svg-tjnHydNk5QjIP3qv .node ellipse,#mermaid-svg-tjnHydNk5QjIP3qv .node polygon,#mermaid-svg-tjnHydNk5QjIP3qv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tjnHydNk5QjIP3qv .rough-node .label text,#mermaid-svg-tjnHydNk5QjIP3qv .node .label text,#mermaid-svg-tjnHydNk5QjIP3qv .image-shape .label,#mermaid-svg-tjnHydNk5QjIP3qv .icon-shape .label{text-anchor:middle;}#mermaid-svg-tjnHydNk5QjIP3qv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tjnHydNk5QjIP3qv .rough-node .label,#mermaid-svg-tjnHydNk5QjIP3qv .node .label,#mermaid-svg-tjnHydNk5QjIP3qv .image-shape .label,#mermaid-svg-tjnHydNk5QjIP3qv .icon-shape .label{text-align:center;}#mermaid-svg-tjnHydNk5QjIP3qv .node.clickable{cursor:pointer;}#mermaid-svg-tjnHydNk5QjIP3qv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tjnHydNk5QjIP3qv .arrowheadPath{fill:#333333;}#mermaid-svg-tjnHydNk5QjIP3qv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tjnHydNk5QjIP3qv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tjnHydNk5QjIP3qv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tjnHydNk5QjIP3qv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tjnHydNk5QjIP3qv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tjnHydNk5QjIP3qv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tjnHydNk5QjIP3qv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tjnHydNk5QjIP3qv .cluster text{fill:#333;}#mermaid-svg-tjnHydNk5QjIP3qv .cluster span{color:#333;}#mermaid-svg-tjnHydNk5QjIP3qv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tjnHydNk5QjIP3qv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tjnHydNk5QjIP3qv rect.text{fill:none;stroke-width:0;}#mermaid-svg-tjnHydNk5QjIP3qv .icon-shape,#mermaid-svg-tjnHydNk5QjIP3qv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tjnHydNk5QjIP3qv .icon-shape p,#mermaid-svg-tjnHydNk5QjIP3qv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tjnHydNk5QjIP3qv .icon-shape .label rect,#mermaid-svg-tjnHydNk5QjIP3qv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tjnHydNk5QjIP3qv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tjnHydNk5QjIP3qv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tjnHydNk5QjIP3qv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Spark DAG调度
Map1
FlatMap
ReduceByKey
Hadoop MapReduce 线性执行
Map1
落盘
Reduce1
落盘
Map2
落盘
Reduce2
2)易用:多语言API
支持Java、Scala、Python(PySpark)、R、SQL,代码简洁,示例:
python
# PySpark DataFrame极简示例
from pyspark.sql import SparkSession
spark = SparkSession.builder.master("local[*]").appName("demo").getOrCreate()
df = spark.read.json("test.json")
df.where("age > 21").select("name").show()
3)通用:一套引擎覆盖全大数据场景
内置5大组件,批处理、SQL、实时流、机器学习、图计算无缝切换。
4)兼容性:多集群、多数据源支持
- 运行集群:Standalone、YARN、Mesos、K8s;
- 存储数据源:HDFS、Hive、MySQL、Cassandra、本地文件等。
2.3 Hadoop生态 VS Spark 详细对比(修正定位错误)
| 对比维度 | Hadoop生态(HDFS+YARN+MapReduce) | Spark |
|---|---|---|
| 产品定位 | 完整大数据平台,包含存储、资源调度、MapReduce计算框架 | 统一内存分布式计算引擎,无存储/调度能力,可对接各类存储、调度系统 |
| 计算组件 | MapReduce,第一代批计算框架 | Spark Core/RDD,内存式计算核心 |
| 中间数据存储 | MapReduce强制落地磁盘,高延迟 | 中间结果优先内存,溢出写磁盘,低延迟 |
| 任务调度 | MapReduce线性分阶段执行,无DAG优化 | DAG有向无环图规划任务,减少Shuffle次数 |
| 适用场景 | 海量冷数据一次性离线批处理 | 离线批、交互式查询、实时流、机器学习迭代计算 |
| 硬件要求 | 集群内存要求低,低配机器可运行 | 对集群内存资源要求更高,硬件成本偏高 |
| 编程范式 | 底层Map+Reduce,算子单一,开发繁琐 | RDD/DF多层API,算子丰富,开发效率高 |
2.4 关键认知:Spark不能替代Hadoop生态
- Spark只负责计算 ,自身不提供分布式存储、集群资源调度,生产环境标配
HDFS存储 + YARN调度 + Spark计算; - Hive数仓、传统离线任务大量基于MapReduce开发,生态稳定成熟,无法完全被Spark替换。
三、Spark完整生态(五大核心模块)
所有组件全部基于Spark Core底层引擎构建:
#mermaid-svg-RclkRr1ZPU63okxU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RclkRr1ZPU63okxU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RclkRr1ZPU63okxU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RclkRr1ZPU63okxU .error-icon{fill:#552222;}#mermaid-svg-RclkRr1ZPU63okxU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RclkRr1ZPU63okxU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RclkRr1ZPU63okxU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RclkRr1ZPU63okxU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RclkRr1ZPU63okxU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RclkRr1ZPU63okxU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RclkRr1ZPU63okxU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RclkRr1ZPU63okxU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RclkRr1ZPU63okxU .marker.cross{stroke:#333333;}#mermaid-svg-RclkRr1ZPU63okxU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RclkRr1ZPU63okxU p{margin:0;}#mermaid-svg-RclkRr1ZPU63okxU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RclkRr1ZPU63okxU .cluster-label text{fill:#333;}#mermaid-svg-RclkRr1ZPU63okxU .cluster-label span{color:#333;}#mermaid-svg-RclkRr1ZPU63okxU .cluster-label span p{background-color:transparent;}#mermaid-svg-RclkRr1ZPU63okxU .label text,#mermaid-svg-RclkRr1ZPU63okxU span{fill:#333;color:#333;}#mermaid-svg-RclkRr1ZPU63okxU .node rect,#mermaid-svg-RclkRr1ZPU63okxU .node circle,#mermaid-svg-RclkRr1ZPU63okxU .node ellipse,#mermaid-svg-RclkRr1ZPU63okxU .node polygon,#mermaid-svg-RclkRr1ZPU63okxU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RclkRr1ZPU63okxU .rough-node .label text,#mermaid-svg-RclkRr1ZPU63okxU .node .label text,#mermaid-svg-RclkRr1ZPU63okxU .image-shape .label,#mermaid-svg-RclkRr1ZPU63okxU .icon-shape .label{text-anchor:middle;}#mermaid-svg-RclkRr1ZPU63okxU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RclkRr1ZPU63okxU .rough-node .label,#mermaid-svg-RclkRr1ZPU63okxU .node .label,#mermaid-svg-RclkRr1ZPU63okxU .image-shape .label,#mermaid-svg-RclkRr1ZPU63okxU .icon-shape .label{text-align:center;}#mermaid-svg-RclkRr1ZPU63okxU .node.clickable{cursor:pointer;}#mermaid-svg-RclkRr1ZPU63okxU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RclkRr1ZPU63okxU .arrowheadPath{fill:#333333;}#mermaid-svg-RclkRr1ZPU63okxU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RclkRr1ZPU63okxU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RclkRr1ZPU63okxU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RclkRr1ZPU63okxU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RclkRr1ZPU63okxU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RclkRr1ZPU63okxU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RclkRr1ZPU63okxU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RclkRr1ZPU63okxU .cluster text{fill:#333;}#mermaid-svg-RclkRr1ZPU63okxU .cluster span{color:#333;}#mermaid-svg-RclkRr1ZPU63okxU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RclkRr1ZPU63okxU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RclkRr1ZPU63okxU rect.text{fill:none;stroke-width:0;}#mermaid-svg-RclkRr1ZPU63okxU .icon-shape,#mermaid-svg-RclkRr1ZPU63okxU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RclkRr1ZPU63okxU .icon-shape p,#mermaid-svg-RclkRr1ZPU63okxU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RclkRr1ZPU63okxU .icon-shape .label rect,#mermaid-svg-RclkRr1ZPU63okxU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RclkRr1ZPU63okxU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RclkRr1ZPU63okxU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RclkRr1ZPU63okxU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Spark Core 底层核心 RDD
Spark SQL 结构化数据
Spark Streaming 微批实时流
MLlib 分布式机器学习
GraphX 分布式图计算
Structured Streaming 流批一体
- Spark Core:Spark底层核心,RDD为基础数据抽象,提供多语言底层API,离线批处理基础;
- Spark SQL:处理结构化数据,抽象DataFrame,支持SQL/DSL双写法,兼容Hive元数据;
- Spark Streaming:基于DStream微批实时计算,处理日志、实时数据流;
- MLlib:分布式机器学习库,内置分类、回归、聚类、协同过滤、特征工程算法;
- GraphX:图计算组件,处理顶点、边结构数据,内置PageRank、连通分量、最短路径。
四、Spark四种运行模式
#mermaid-svg-SnUU4QWpWto0uaIF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SnUU4QWpWto0uaIF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SnUU4QWpWto0uaIF .error-icon{fill:#552222;}#mermaid-svg-SnUU4QWpWto0uaIF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SnUU4QWpWto0uaIF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SnUU4QWpWto0uaIF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SnUU4QWpWto0uaIF .marker.cross{stroke:#333333;}#mermaid-svg-SnUU4QWpWto0uaIF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SnUU4QWpWto0uaIF p{margin:0;}#mermaid-svg-SnUU4QWpWto0uaIF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SnUU4QWpWto0uaIF .cluster-label text{fill:#333;}#mermaid-svg-SnUU4QWpWto0uaIF .cluster-label span{color:#333;}#mermaid-svg-SnUU4QWpWto0uaIF .cluster-label span p{background-color:transparent;}#mermaid-svg-SnUU4QWpWto0uaIF .label text,#mermaid-svg-SnUU4QWpWto0uaIF span{fill:#333;color:#333;}#mermaid-svg-SnUU4QWpWto0uaIF .node rect,#mermaid-svg-SnUU4QWpWto0uaIF .node circle,#mermaid-svg-SnUU4QWpWto0uaIF .node ellipse,#mermaid-svg-SnUU4QWpWto0uaIF .node polygon,#mermaid-svg-SnUU4QWpWto0uaIF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SnUU4QWpWto0uaIF .rough-node .label text,#mermaid-svg-SnUU4QWpWto0uaIF .node .label text,#mermaid-svg-SnUU4QWpWto0uaIF .image-shape .label,#mermaid-svg-SnUU4QWpWto0uaIF .icon-shape .label{text-anchor:middle;}#mermaid-svg-SnUU4QWpWto0uaIF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SnUU4QWpWto0uaIF .rough-node .label,#mermaid-svg-SnUU4QWpWto0uaIF .node .label,#mermaid-svg-SnUU4QWpWto0uaIF .image-shape .label,#mermaid-svg-SnUU4QWpWto0uaIF .icon-shape .label{text-align:center;}#mermaid-svg-SnUU4QWpWto0uaIF .node.clickable{cursor:pointer;}#mermaid-svg-SnUU4QWpWto0uaIF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SnUU4QWpWto0uaIF .arrowheadPath{fill:#333333;}#mermaid-svg-SnUU4QWpWto0uaIF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SnUU4QWpWto0uaIF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SnUU4QWpWto0uaIF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SnUU4QWpWto0uaIF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SnUU4QWpWto0uaIF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SnUU4QWpWto0uaIF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SnUU4QWpWto0uaIF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SnUU4QWpWto0uaIF .cluster text{fill:#333;}#mermaid-svg-SnUU4QWpWto0uaIF .cluster span{color:#333;}#mermaid-svg-SnUU4QWpWto0uaIF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SnUU4QWpWto0uaIF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SnUU4QWpWto0uaIF rect.text{fill:none;stroke-width:0;}#mermaid-svg-SnUU4QWpWto0uaIF .icon-shape,#mermaid-svg-SnUU4QWpWto0uaIF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SnUU4QWpWto0uaIF .icon-shape p,#mermaid-svg-SnUU4QWpWto0uaIF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SnUU4QWpWto0uaIF .icon-shape .label rect,#mermaid-svg-SnUU4QWpWto0uaIF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SnUU4QWpWto0uaIF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SnUU4QWpWto0uaIF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SnUU4QWpWto0uaIF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Spark运行模式
Local本地模式
Standalone独立集群
YARN集群 生产主流
Kubernetes云原生容器
- Local本地模式:单机多线程模拟集群,仅用于开发、测试,线上禁止使用;
- Standalone:Spark自研资源调度,无需依赖Hadoop,小型离线集群使用;
- YARN模式:企业生产标准方案,Spark任务运行在YARN容器,集群资源复用率最高;
- K8s模式:Spark2.3后支持,云原生容器化部署,云上大数据平台专用。
五、Spark集群核心架构与角色
5.1 四大核心角色:Driver、Master、Worker、Executor
#mermaid-svg-EpXlQmuweyFgTQmw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EpXlQmuweyFgTQmw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EpXlQmuweyFgTQmw .error-icon{fill:#552222;}#mermaid-svg-EpXlQmuweyFgTQmw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EpXlQmuweyFgTQmw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EpXlQmuweyFgTQmw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EpXlQmuweyFgTQmw .marker.cross{stroke:#333333;}#mermaid-svg-EpXlQmuweyFgTQmw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EpXlQmuweyFgTQmw p{margin:0;}#mermaid-svg-EpXlQmuweyFgTQmw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EpXlQmuweyFgTQmw .cluster-label text{fill:#333;}#mermaid-svg-EpXlQmuweyFgTQmw .cluster-label span{color:#333;}#mermaid-svg-EpXlQmuweyFgTQmw .cluster-label span p{background-color:transparent;}#mermaid-svg-EpXlQmuweyFgTQmw .label text,#mermaid-svg-EpXlQmuweyFgTQmw span{fill:#333;color:#333;}#mermaid-svg-EpXlQmuweyFgTQmw .node rect,#mermaid-svg-EpXlQmuweyFgTQmw .node circle,#mermaid-svg-EpXlQmuweyFgTQmw .node ellipse,#mermaid-svg-EpXlQmuweyFgTQmw .node polygon,#mermaid-svg-EpXlQmuweyFgTQmw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EpXlQmuweyFgTQmw .rough-node .label text,#mermaid-svg-EpXlQmuweyFgTQmw .node .label text,#mermaid-svg-EpXlQmuweyFgTQmw .image-shape .label,#mermaid-svg-EpXlQmuweyFgTQmw .icon-shape .label{text-anchor:middle;}#mermaid-svg-EpXlQmuweyFgTQmw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EpXlQmuweyFgTQmw .rough-node .label,#mermaid-svg-EpXlQmuweyFgTQmw .node .label,#mermaid-svg-EpXlQmuweyFgTQmw .image-shape .label,#mermaid-svg-EpXlQmuweyFgTQmw .icon-shape .label{text-align:center;}#mermaid-svg-EpXlQmuweyFgTQmw .node.clickable{cursor:pointer;}#mermaid-svg-EpXlQmuweyFgTQmw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EpXlQmuweyFgTQmw .arrowheadPath{fill:#333333;}#mermaid-svg-EpXlQmuweyFgTQmw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EpXlQmuweyFgTQmw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EpXlQmuweyFgTQmw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EpXlQmuweyFgTQmw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EpXlQmuweyFgTQmw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EpXlQmuweyFgTQmw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EpXlQmuweyFgTQmw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EpXlQmuweyFgTQmw .cluster text{fill:#333;}#mermaid-svg-EpXlQmuweyFgTQmw .cluster span{color:#333;}#mermaid-svg-EpXlQmuweyFgTQmw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EpXlQmuweyFgTQmw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EpXlQmuweyFgTQmw rect.text{fill:none;stroke-width:0;}#mermaid-svg-EpXlQmuweyFgTQmw .icon-shape,#mermaid-svg-EpXlQmuweyFgTQmw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EpXlQmuweyFgTQmw .icon-shape p,#mermaid-svg-EpXlQmuweyFgTQmw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EpXlQmuweyFgTQmw .icon-shape .label rect,#mermaid-svg-EpXlQmuweyFgTQmw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EpXlQmuweyFgTQmw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EpXlQmuweyFgTQmw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EpXlQmuweyFgTQmw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Standalone集群
Driver 驱动程序
Master 集群资源管理者
Worker 节点进程1
Worker 节点进程2
Executor 执行器1
Task 计算任务
内存缓存RDD
Executor 执行器2
Task 计算任务
- Driver :程序主入口,创建
SparkContext/SparkSession,封装任务、生成DAG、调度任务; - Master(仅Standalone模式):集群资源总管,分配内存CPU给Worker节点;
- Worker:每台服务器守护进程,接收Master指令,启动Executor;
- Executor:运行在节点的执行进程,执行Task,缓存RDD数据,负责实际计算。
第二章 Spark RDD 核心(Spark底层基石)
2.1 RDD定义与三大特性
RDD全称Resilient Distributed Dataset 弹性分布式数据集,Spark最基础数据抽象,代表不可变、可分区、支持并行计算的分布式集合。
- Resilient弹性:数据可存内存/磁盘,分区丢失可依赖血缘自动重算;
- Distributed分布式:数据拆分多分区,跨多节点并行运算;
- Dataset数据集:承载批量结构化/非结构化数据。
三大核心特性:不可变、分区存储、并行计算
#mermaid-svg-BcZuMog3JOG8YIbp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BcZuMog3JOG8YIbp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BcZuMog3JOG8YIbp .error-icon{fill:#552222;}#mermaid-svg-BcZuMog3JOG8YIbp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BcZuMog3JOG8YIbp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BcZuMog3JOG8YIbp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BcZuMog3JOG8YIbp .marker.cross{stroke:#333333;}#mermaid-svg-BcZuMog3JOG8YIbp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BcZuMog3JOG8YIbp p{margin:0;}#mermaid-svg-BcZuMog3JOG8YIbp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BcZuMog3JOG8YIbp .cluster-label text{fill:#333;}#mermaid-svg-BcZuMog3JOG8YIbp .cluster-label span{color:#333;}#mermaid-svg-BcZuMog3JOG8YIbp .cluster-label span p{background-color:transparent;}#mermaid-svg-BcZuMog3JOG8YIbp .label text,#mermaid-svg-BcZuMog3JOG8YIbp span{fill:#333;color:#333;}#mermaid-svg-BcZuMog3JOG8YIbp .node rect,#mermaid-svg-BcZuMog3JOG8YIbp .node circle,#mermaid-svg-BcZuMog3JOG8YIbp .node ellipse,#mermaid-svg-BcZuMog3JOG8YIbp .node polygon,#mermaid-svg-BcZuMog3JOG8YIbp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BcZuMog3JOG8YIbp .rough-node .label text,#mermaid-svg-BcZuMog3JOG8YIbp .node .label text,#mermaid-svg-BcZuMog3JOG8YIbp .image-shape .label,#mermaid-svg-BcZuMog3JOG8YIbp .icon-shape .label{text-anchor:middle;}#mermaid-svg-BcZuMog3JOG8YIbp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BcZuMog3JOG8YIbp .rough-node .label,#mermaid-svg-BcZuMog3JOG8YIbp .node .label,#mermaid-svg-BcZuMog3JOG8YIbp .image-shape .label,#mermaid-svg-BcZuMog3JOG8YIbp .icon-shape .label{text-align:center;}#mermaid-svg-BcZuMog3JOG8YIbp .node.clickable{cursor:pointer;}#mermaid-svg-BcZuMog3JOG8YIbp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BcZuMog3JOG8YIbp .arrowheadPath{fill:#333333;}#mermaid-svg-BcZuMog3JOG8YIbp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BcZuMog3JOG8YIbp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BcZuMog3JOG8YIbp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BcZuMog3JOG8YIbp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BcZuMog3JOG8YIbp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BcZuMog3JOG8YIbp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BcZuMog3JOG8YIbp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BcZuMog3JOG8YIbp .cluster text{fill:#333;}#mermaid-svg-BcZuMog3JOG8YIbp .cluster span{color:#333;}#mermaid-svg-BcZuMog3JOG8YIbp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BcZuMog3JOG8YIbp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BcZuMog3JOG8YIbp rect.text{fill:none;stroke-width:0;}#mermaid-svg-BcZuMog3JOG8YIbp .icon-shape,#mermaid-svg-BcZuMog3JOG8YIbp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BcZuMog3JOG8YIbp .icon-shape p,#mermaid-svg-BcZuMog3JOG8YIbp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BcZuMog3JOG8YIbp .icon-shape .label rect,#mermaid-svg-BcZuMog3JOG8YIbp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BcZuMog3JOG8YIbp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BcZuMog3JOG8YIbp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BcZuMog3JOG8YIbp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} RDD弹性分布式数据集
不可变Immutable
分区Partition 数据分片
并行计算 1分区对应1个Task
2.2 RDD创建两种方式
方式1:并行化本地集合(本地数据转分布式RDD)
python
from pyspark import SparkConf, SparkContext
if __name__ == '__main__':
conf = SparkConf().setAppName("createRDD").setMaster("local[*]")
sc = SparkContext(conf=conf)
# 本地列表转为RDD,numslices指定分区数量
data = [1,2,3,4,5,6,7,8,9]
rdd = sc.parallelize(data, numSlices=3)
print(rdd.collect())
方式2:读取外部文件(本地/HDFS文件)
python
from pyspark import SparkConf, SparkContext
if __name__ == '__main__':
conf = SparkConf().setAppName("fileRDD").setMaster("local[*]")
sc = SparkContext(conf=conf)
# 读取本地文件
rdd_local = sc.textFile("../data/words.txt")
# 读取HDFS分布式文件
rdd_hdfs = sc.textFile("hdfs://node1:8020/input/words.txt")
print("RDD分区数:", rdd_hdfs.getNumPartitions())
2.3 RDD算子分类:Transformation(转换)、Action(行动)
核心规则
- Transformation转换算子 :返回全新RDD,懒加载机制,仅记录数据依赖关系,不执行真实计算;
- Action行动算子:返回非RDD类型结果,触发Job提交,执行完整计算链路。
#mermaid-svg-RqBbuHTqyLi0UcMG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RqBbuHTqyLi0UcMG .error-icon{fill:#552222;}#mermaid-svg-RqBbuHTqyLi0UcMG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RqBbuHTqyLi0UcMG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RqBbuHTqyLi0UcMG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RqBbuHTqyLi0UcMG .marker.cross{stroke:#333333;}#mermaid-svg-RqBbuHTqyLi0UcMG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RqBbuHTqyLi0UcMG p{margin:0;}#mermaid-svg-RqBbuHTqyLi0UcMG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG .cluster-label text{fill:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG .cluster-label span{color:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG .cluster-label span p{background-color:transparent;}#mermaid-svg-RqBbuHTqyLi0UcMG .label text,#mermaid-svg-RqBbuHTqyLi0UcMG span{fill:#333;color:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG .node rect,#mermaid-svg-RqBbuHTqyLi0UcMG .node circle,#mermaid-svg-RqBbuHTqyLi0UcMG .node ellipse,#mermaid-svg-RqBbuHTqyLi0UcMG .node polygon,#mermaid-svg-RqBbuHTqyLi0UcMG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RqBbuHTqyLi0UcMG .rough-node .label text,#mermaid-svg-RqBbuHTqyLi0UcMG .node .label text,#mermaid-svg-RqBbuHTqyLi0UcMG .image-shape .label,#mermaid-svg-RqBbuHTqyLi0UcMG .icon-shape .label{text-anchor:middle;}#mermaid-svg-RqBbuHTqyLi0UcMG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RqBbuHTqyLi0UcMG .rough-node .label,#mermaid-svg-RqBbuHTqyLi0UcMG .node .label,#mermaid-svg-RqBbuHTqyLi0UcMG .image-shape .label,#mermaid-svg-RqBbuHTqyLi0UcMG .icon-shape .label{text-align:center;}#mermaid-svg-RqBbuHTqyLi0UcMG .node.clickable{cursor:pointer;}#mermaid-svg-RqBbuHTqyLi0UcMG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RqBbuHTqyLi0UcMG .arrowheadPath{fill:#333333;}#mermaid-svg-RqBbuHTqyLi0UcMG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RqBbuHTqyLi0UcMG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RqBbuHTqyLi0UcMG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RqBbuHTqyLi0UcMG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RqBbuHTqyLi0UcMG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RqBbuHTqyLi0UcMG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RqBbuHTqyLi0UcMG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RqBbuHTqyLi0UcMG .cluster text{fill:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG .cluster span{color:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RqBbuHTqyLi0UcMG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RqBbuHTqyLi0UcMG rect.text{fill:none;stroke-width:0;}#mermaid-svg-RqBbuHTqyLi0UcMG .icon-shape,#mermaid-svg-RqBbuHTqyLi0UcMG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RqBbuHTqyLi0UcMG .icon-shape p,#mermaid-svg-RqBbuHTqyLi0UcMG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RqBbuHTqyLi0UcMG .icon-shape .label rect,#mermaid-svg-RqBbuHTqyLi0UcMG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RqBbuHTqyLi0UcMG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RqBbuHTqyLi0UcMG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RqBbuHTqyLi0UcMG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 原始RDD
map转换算子
flatMap转换算子
reduceByKey转换算子
collect Action算子 触发Job
2.4 常用Transformation转换算子代码示例
1)map:逐条处理单个元素
python
rdd = sc.parallelize([1,2,3,4,5])
map_rdd = rdd.map(lambda x: x * 3)
print(map_rdd.collect()) # [3,6,9,12,15]
2)flatMap:映射 + 扁平化拆解
python
rdd = sc.parallelize(["hello spark", "hello hadoop"])
flat_rdd = rdd.flatMap(lambda line: line.split(" "))
print(flat_rdd.collect()) # ['hello','spark','hello','hadoop']
3)reduceByKey:KV键值对按Key聚合
python
rdd = sc.parallelize([("a",1),("a",1),("b",1),("b",1),("b",1)])
res = rdd.reduceByKey(lambda a,b: a+b)
print(res.collect()) # [('a', 2), ('b', 3)]
4)filter、distinct、join、groupByKey、sortByKey等算子原理一致,可自行测试
2.5 常用Action行动算子代码示例
python
rdd = sc.parallelize([1,2,3,4,5])
print(rdd.count()) # count:统计总元素 5
print(rdd.first()) # first:取首个元素 1
print(rdd.reduce(lambda a,b: a+b)) # reduce全局求和 15
rdd.saveAsTextFile("./output") # 结果写入文件
2.6 分区操作算子
mapPartitions:按分区批量处理,每个分区仅执行一次逻辑,适合数据库连接等重量级初始化;repartition:强制Shuffle,增加/减少分区;coalesce:默认无Shuffle,多用于减少分区;partitionBy:仅KV型RDD可用,自定义分区分发规则。
2.7 RDD持久化(缓存)
为什么需要缓存?
RDD惰性求值,多次复用同一RDD时,会重复完整重算上游所有依赖,迭代计算性能损耗巨大。缓存将计算结果持久化内存/磁盘,复用无需重复计算。
缓存API
python
rdd.cache() # 等价于 StorageLevel.MEMORY_ONLY
# 自定义存储级别(内存放不下自动落盘,推荐生产使用)
rdd.persist(StorageLevel.MEMORY_AND_DISK)
# 手动释放缓存资源
rdd.unpersist()
主流存储级别:MEMORY_ONLY、MEMORY_AND_DISK、DISK_ONLY、_2副本、堆外内存OFF_HEAP。
2.8 Spark共享变量(修复累加器global冗余问题)
1)广播变量 Broadcast
普通变量会拷贝到每一个Task,内存大量冗余;广播变量每个Executor仅保存一份副本,节点内所有Task共享,只读不可修改。
python
# 小型映射字典广播
dict_map = {101:"广东",102:"北京",103:"上海"}
bc = sc.broadcast(dict_map)
user_rdd = sc.parallelize([101,102,103])
res = user_rdd.map(lambda x: (x, bc.value.get(x)))
2)累加器 Accumulator(删除多余global关键字)
普通本地变量无法跨Executor分布式累加,累加器专为分布式计数设计,仅Driver端可读取最终值。
python
acc = sc.accumulator(0)
rdd = sc.parallelize([1,15,8,22])
# 移除多余global,直接调用acc.add()
def count_big(x):
if x > 10:
acc.add(1)
return x
rdd.map(count_big).collect()
print("大于10的数字数量:", acc.value)
说明:累加器通过闭包序列化传递对象引用,无需global声明,官方标准示例均无此关键字,避免误导初学者。
2.9 RDD依赖:窄依赖 & 宽依赖(Shuffle)
#mermaid-svg-qo8OQzX635e6HLEH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qo8OQzX635e6HLEH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qo8OQzX635e6HLEH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qo8OQzX635e6HLEH .error-icon{fill:#552222;}#mermaid-svg-qo8OQzX635e6HLEH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qo8OQzX635e6HLEH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qo8OQzX635e6HLEH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qo8OQzX635e6HLEH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qo8OQzX635e6HLEH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qo8OQzX635e6HLEH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qo8OQzX635e6HLEH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qo8OQzX635e6HLEH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qo8OQzX635e6HLEH .marker.cross{stroke:#333333;}#mermaid-svg-qo8OQzX635e6HLEH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qo8OQzX635e6HLEH p{margin:0;}#mermaid-svg-qo8OQzX635e6HLEH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qo8OQzX635e6HLEH .cluster-label text{fill:#333;}#mermaid-svg-qo8OQzX635e6HLEH .cluster-label span{color:#333;}#mermaid-svg-qo8OQzX635e6HLEH .cluster-label span p{background-color:transparent;}#mermaid-svg-qo8OQzX635e6HLEH .label text,#mermaid-svg-qo8OQzX635e6HLEH span{fill:#333;color:#333;}#mermaid-svg-qo8OQzX635e6HLEH .node rect,#mermaid-svg-qo8OQzX635e6HLEH .node circle,#mermaid-svg-qo8OQzX635e6HLEH .node ellipse,#mermaid-svg-qo8OQzX635e6HLEH .node polygon,#mermaid-svg-qo8OQzX635e6HLEH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qo8OQzX635e6HLEH .rough-node .label text,#mermaid-svg-qo8OQzX635e6HLEH .node .label text,#mermaid-svg-qo8OQzX635e6HLEH .image-shape .label,#mermaid-svg-qo8OQzX635e6HLEH .icon-shape .label{text-anchor:middle;}#mermaid-svg-qo8OQzX635e6HLEH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qo8OQzX635e6HLEH .rough-node .label,#mermaid-svg-qo8OQzX635e6HLEH .node .label,#mermaid-svg-qo8OQzX635e6HLEH .image-shape .label,#mermaid-svg-qo8OQzX635e6HLEH .icon-shape .label{text-align:center;}#mermaid-svg-qo8OQzX635e6HLEH .node.clickable{cursor:pointer;}#mermaid-svg-qo8OQzX635e6HLEH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qo8OQzX635e6HLEH .arrowheadPath{fill:#333333;}#mermaid-svg-qo8OQzX635e6HLEH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qo8OQzX635e6HLEH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qo8OQzX635e6HLEH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qo8OQzX635e6HLEH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qo8OQzX635e6HLEH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qo8OQzX635e6HLEH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qo8OQzX635e6HLEH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qo8OQzX635e6HLEH .cluster text{fill:#333;}#mermaid-svg-qo8OQzX635e6HLEH .cluster span{color:#333;}#mermaid-svg-qo8OQzX635e6HLEH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qo8OQzX635e6HLEH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qo8OQzX635e6HLEH rect.text{fill:none;stroke-width:0;}#mermaid-svg-qo8OQzX635e6HLEH .icon-shape,#mermaid-svg-qo8OQzX635e6HLEH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qo8OQzX635e6HLEH .icon-shape p,#mermaid-svg-qo8OQzX635e6HLEH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qo8OQzX635e6HLEH .icon-shape .label rect,#mermaid-svg-qo8OQzX635e6HLEH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qo8OQzX635e6HLEH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qo8OQzX635e6HLEH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qo8OQzX635e6HLEH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 宽依赖 WideDependency 触发Shuffle
父分区1
子分区1
子分区2
父分区2
窄依赖 NarrowDependency
父分区1
子分区1
父分区2
子分区2
- 窄依赖:一个父分区数据仅供给单个子分区,无跨节点Shuffle,如map、filter、union;
- 宽依赖:单个父分区数据分发至多个子分区,触发跨节点Shuffle,如reduceByKey、groupByKey;
- Stage划分规则:DAG从后往前遍历,遇到宽依赖切割Stage,同一个Stage内所有Task并行执行。
第三章 Spark SQL 结构化数据处理
3.1 Spark SQL概述
Spark SQL是Spark处理结构化数据的专用模块,支持SQL、DSL两套开发语法,内置Catalyst自动优化器,兼容Hive元数据,是企业离线数仓主流技术。
3.2 DataFrame与RDD区别
| 维度 | RDD | DataFrame |
|---|---|---|
| 数据结构 | 无固定Schema,任意混合数据 | 标准二维表,自带Schema(列名、数据类型、是否为空) |
| 执行优化 | 无内置优化,完全依赖开发人员 | Catalyst自动优化(谓词下推、列裁剪) |
| 开发语法 | 底层算子,代码冗长 | 简洁SQL/DSL API,易上手 |
| 底层抽象 | 分布式数据集合 | 带元数据的分布式数据表 |
3.3 统一入口:SparkSession(Spark2.0+标准入口)
python
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("SparkSQLDemo") \
.master("local[*]") \
.config("spark.sql.shuffle.partitions", "4") \
.getOrCreate()
# 获取底层SparkContext对象
sc = spark.sparkContext
3.4 DataFrame四种创建方式
- 已有RDD转换为DataFrame;
- Pandas单机DataFrame转为分布式Spark DataFrame;
- 读取外部文件:csv/json/parquet/text;
- JDBC读取MySQL、Oracle等数据库;
读取CSV文件示例
python
df = spark.read.csv(
"./stu_score.txt",
sep=",",
header=False,
inferSchema=True
).toDF("id", "subject", "score")
df.printSchema()
df.show()
3.5 两种开发风格:SQL & DSL
DSL风格(链式API调用)
python
# 过滤语文成绩数据
df.where("subject = '语文'").limit(5).show()
# 按学科分组求平均分
df.groupBy("subject").avg("score").show()
SQL风格(标准SQL语句)
python
# 注册临时视图(仅当前SparkSession生效)
df.createOrReplaceTempView("score")
# 执行SQL查询
spark.sql("SELECT * FROM score WHERE subject='语文' LIMIT 5").show()
3.6 数据清洗高频API
python
df.dropDuplicates(["id"]) # 指定字段去重
df.dropna(how="any") # 任意字段为空则删除整行
df.fillna(0, subset=["score"]) # 指定列空值填充0
3.7 数据写出四种模式
写出mode可选:overwrite覆盖、append追加、ignore忽略、errorifexists(默认报错)
python
# 写出parquet列式文件(Spark默认存储格式)
df.write.mode("overwrite").format("parquet").save("./output/parquet")
# JDBC写入MySQL数据表
df.write.format("jdbc") \
.option("url", "jdbc:mysql://node1:3306/test") \
.option("dbtable", "score") \
.option("user", "root") \
.option("password", "123456") \
.save()
3.8 Catalyst优化器完整执行流程
#mermaid-svg-kG5oHSHAfrj56ZH9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kG5oHSHAfrj56ZH9 .error-icon{fill:#552222;}#mermaid-svg-kG5oHSHAfrj56ZH9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kG5oHSHAfrj56ZH9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .marker.cross{stroke:#333333;}#mermaid-svg-kG5oHSHAfrj56ZH9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kG5oHSHAfrj56ZH9 p{margin:0;}#mermaid-svg-kG5oHSHAfrj56ZH9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .cluster-label text{fill:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .cluster-label span{color:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .cluster-label span p{background-color:transparent;}#mermaid-svg-kG5oHSHAfrj56ZH9 .label text,#mermaid-svg-kG5oHSHAfrj56ZH9 span{fill:#333;color:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .node rect,#mermaid-svg-kG5oHSHAfrj56ZH9 .node circle,#mermaid-svg-kG5oHSHAfrj56ZH9 .node ellipse,#mermaid-svg-kG5oHSHAfrj56ZH9 .node polygon,#mermaid-svg-kG5oHSHAfrj56ZH9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .rough-node .label text,#mermaid-svg-kG5oHSHAfrj56ZH9 .node .label text,#mermaid-svg-kG5oHSHAfrj56ZH9 .image-shape .label,#mermaid-svg-kG5oHSHAfrj56ZH9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-kG5oHSHAfrj56ZH9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .rough-node .label,#mermaid-svg-kG5oHSHAfrj56ZH9 .node .label,#mermaid-svg-kG5oHSHAfrj56ZH9 .image-shape .label,#mermaid-svg-kG5oHSHAfrj56ZH9 .icon-shape .label{text-align:center;}#mermaid-svg-kG5oHSHAfrj56ZH9 .node.clickable{cursor:pointer;}#mermaid-svg-kG5oHSHAfrj56ZH9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .arrowheadPath{fill:#333333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kG5oHSHAfrj56ZH9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kG5oHSHAfrj56ZH9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kG5oHSHAfrj56ZH9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kG5oHSHAfrj56ZH9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .cluster text{fill:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 .cluster span{color:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kG5oHSHAfrj56ZH9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kG5oHSHAfrj56ZH9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-kG5oHSHAfrj56ZH9 .icon-shape,#mermaid-svg-kG5oHSHAfrj56ZH9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kG5oHSHAfrj56ZH9 .icon-shape p,#mermaid-svg-kG5oHSHAfrj56ZH9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kG5oHSHAfrj56ZH9 .icon-shape .label rect,#mermaid-svg-kG5oHSHAfrj56ZH9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kG5oHSHAfrj56ZH9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kG5oHSHAfrj56ZH9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kG5oHSHAfrj56ZH9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入SQL语句
抽象语法树
绑定表元数据、字段类型
未优化原始逻辑计划
优化器:谓词下推、列裁剪
最优逻辑执行计划
生成物理执行计划
动态代码生成,转为RDD任务
两大核心优化手段:
- 谓词下推:Filter过滤逻辑提前执行,减少上下游传输数据量;
- 列裁剪:仅读取SQL中用到的字段,避免全表扫描浪费IO。
第四章 Spark Streaming & Structured Streaming 实时流计算
4.1 流数据特点
无限持续生成、实时到达,典型业务场景:电商实时大屏、物联网设备监控、日志实时分析。
4.2 两种主流流式计算模型
- 原生单条流处理:Flink/Storm,逐条处理数据,毫秒级低延迟;
- 微批处理:Spark Streaming/Structured Streaming,按固定时间切片生成小批量数据,秒级延迟。
#mermaid-svg-hVZrCkDTh9hXjqaB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hVZrCkDTh9hXjqaB .error-icon{fill:#552222;}#mermaid-svg-hVZrCkDTh9hXjqaB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hVZrCkDTh9hXjqaB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hVZrCkDTh9hXjqaB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hVZrCkDTh9hXjqaB .marker.cross{stroke:#333333;}#mermaid-svg-hVZrCkDTh9hXjqaB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hVZrCkDTh9hXjqaB p{margin:0;}#mermaid-svg-hVZrCkDTh9hXjqaB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB .cluster-label text{fill:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB .cluster-label span{color:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB .cluster-label span p{background-color:transparent;}#mermaid-svg-hVZrCkDTh9hXjqaB .label text,#mermaid-svg-hVZrCkDTh9hXjqaB span{fill:#333;color:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB .node rect,#mermaid-svg-hVZrCkDTh9hXjqaB .node circle,#mermaid-svg-hVZrCkDTh9hXjqaB .node ellipse,#mermaid-svg-hVZrCkDTh9hXjqaB .node polygon,#mermaid-svg-hVZrCkDTh9hXjqaB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hVZrCkDTh9hXjqaB .rough-node .label text,#mermaid-svg-hVZrCkDTh9hXjqaB .node .label text,#mermaid-svg-hVZrCkDTh9hXjqaB .image-shape .label,#mermaid-svg-hVZrCkDTh9hXjqaB .icon-shape .label{text-anchor:middle;}#mermaid-svg-hVZrCkDTh9hXjqaB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hVZrCkDTh9hXjqaB .rough-node .label,#mermaid-svg-hVZrCkDTh9hXjqaB .node .label,#mermaid-svg-hVZrCkDTh9hXjqaB .image-shape .label,#mermaid-svg-hVZrCkDTh9hXjqaB .icon-shape .label{text-align:center;}#mermaid-svg-hVZrCkDTh9hXjqaB .node.clickable{cursor:pointer;}#mermaid-svg-hVZrCkDTh9hXjqaB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hVZrCkDTh9hXjqaB .arrowheadPath{fill:#333333;}#mermaid-svg-hVZrCkDTh9hXjqaB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hVZrCkDTh9hXjqaB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hVZrCkDTh9hXjqaB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hVZrCkDTh9hXjqaB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hVZrCkDTh9hXjqaB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hVZrCkDTh9hXjqaB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hVZrCkDTh9hXjqaB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hVZrCkDTh9hXjqaB .cluster text{fill:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB .cluster span{color:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hVZrCkDTh9hXjqaB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hVZrCkDTh9hXjqaB rect.text{fill:none;stroke-width:0;}#mermaid-svg-hVZrCkDTh9hXjqaB .icon-shape,#mermaid-svg-hVZrCkDTh9hXjqaB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hVZrCkDTh9hXjqaB .icon-shape p,#mermaid-svg-hVZrCkDTh9hXjqaB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hVZrCkDTh9hXjqaB .icon-shape .label rect,#mermaid-svg-hVZrCkDTh9hXjqaB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hVZrCkDTh9hXjqaB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hVZrCkDTh9hXjqaB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hVZrCkDTh9hXjqaB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 无限数据流
按时间切片生成微批
单批次对应1个RDD
连续RDD序列组成DStream
4.3 Spark Streaming核心抽象:DStream
DStream = 时间有序的连续RDD集合,每一个批间隔生成独立RDD;对DStream的所有操作,底层等价操作对应批次RDD。
支持主流数据源
Socket套接字、HDFS文件流、Kafka、Flume、RDD队列流。
DStream算子三大分类
- 无状态算子:仅处理当前批次,不保存历史数据 map/flatMap/filter/join;
- 有状态算子 :跨批次复用历史数据
- window窗口操作:窗口长度、滑动间隔双参数;
- updateStateByKey:全局累计统计;
- 输出算子:print、saveAsTextFiles、foreachRDD(通用自定义输出)。
窗口计算示例
python
# 窗口时长3秒,滑动间隔1秒,实时统计单词数量
words = lines.flatMap(lambda x: x.split(" "))
window_words = words.window(windowDuration=3, slideDuration=1)
window_words.count().pprint()
4.4 Structured Streaming 流批一体(修复complete模式报错问题)
基于Spark SQL DataFrame构建,将无限数据流视为持续追加的动态表,同一套API兼容批/流计算,自动管理计算状态,支持Exactly-Once精确一次语义。
修正后Socket词频代码(解决complete异常)
python
from pyspark.sql import SparkSession
from pyspark.sql.functions import split, explode
spark = SparkSession.builder \
.master("local[2]") \
.appName("StructuredStreamingWordCountSocket") \
.getOrCreate()
# 读取Socket实时流数据源
df = spark.readStream.format("socket")\
.option("host", "localhost")\
.option("port", 9999).load()
# 拆分单词并分组计数
word_df = df.select(explode(split("value", " ")).alias("word")) \
.groupBy("word").count()
# 修改outputMode为update,适配Socket无界聚合场景
query = word_df.writeStream \
.outputMode("update") \
.format("console") \
.trigger(processingTime="5 seconds") \
.start()
query.awaitTermination()
补充说明:
update模式:仅输出当前批次发生变化的聚合结果,适配Socket无界无水印数据源;complete完整模式:输出全量历史聚合数据,仅支持有界文件源、带水印窗口聚合,Socket直接使用会抛出AnalysisException;append追加模式:仅输出新增原始数据,聚合类查询无法使用。
第五章 Spark MLlib & GraphX
5.1 MLlib分布式机器学习库
基于Spark Core构建分布式机器学习工具包,解决单机sklearn无法处理TB级海量样本的痛点:
- 支持任务:分类、回归、聚类、协同过滤、特征工程、Pipeline训练流水线;
- 优势:分布式并行训练,支持海量数据离线建模。
5.2 GraphX图计算组件
Spark提供两套图计算API,分别适配不同开发场景:
- GraphX:底层基于RDD实现,内置PageRank、连通分量、三角形计数、最短路径经典图算法;
- GraphFrames:基于DataFrame封装,无缝对接Spark SQL,语法更简洁易读。
文末总结
- Spark依靠内存计算+DAG调度解决MapReduce磁盘IO瓶颈,五大生态组件覆盖批、SQL、实时、机器学习、图计算全大数据场景;
- RDD是Spark底层核心,吃透懒加载、宽窄依赖、缓存、共享变量是调优基础;
- Spark SQL基于DataFrame+Catalyst优化器,企业离线数仓主流开发框架;
- Spark Streaming为传统微批实时方案,Structured Streaming新一代流批一体框架;
- MLlib、GraphX分别解决分布式机器学习、大规模图结构数据分析场景。
互动&收藏
本文配套Mermaid原理图、可直接运行PySpark代码,零基础友好,适合收藏反复复习。
后续更新Spark性能调优、YARN集群部署、Kafka实时数仓实战项目,有疑问欢迎评论区留言交流!