Files
spark_20260915/README.md
T
2026-09-18 01:12:28 +08:00

753 lines
12 KiB
Markdown

# Spark 学习项目
基于 **Scala + Java** 的 Apache Spark 学习与练习项目。
本项目主要用于个人学习和记录 Spark,从 Spark 基础、RDD、PairRDD、Shuffle、Partition 逐步深入,同时保留线下课程中的 DataFrame、缓存、Checkpoint、YARN 提交等示例代码。
项目以 **Scala 为主,Java 为辅**,代码按照课程进行拆分,每一课尽量保持独立,方便学习、复习和实验。
---
## 项目目标
通过循序渐进的练习掌握 Spark Core 的核心概念,并逐步过渡到 Spark SQL。
学习重点包括:
- Spark 应用程序的基本结构
- `SparkConf`、`SparkContext`
- RDD 的创建、转换和行动
- `map`、`filter`、`flatMap`、`reduce`、`foreach`
- PairRDD 与 `reduceByKey`
- `groupByKey` 与 `reduceByKey`
- Shuffle 的基本原理
- RDD Partition 分区
- `glom`、`repartition`、`coalesce`
- `partitionBy`
- 自定义 `Partitioner`
- WordCount
- Spark SQL / DataFrame
- Cache、Persist、Checkpoint
- Spark 程序打包及 YARN 提交
---
## 技术栈
| 技术 | 版本 / 说明 |
| --- | --- |
| JDK | 8 |
| Scala | 2.11.12 |
| Apache Spark | 2.4.3 |
| Hadoop Client | 2.7.3 |
| MySQL | 8.0.28 |
| HikariCP | 4.0.3 |
| commons-dbutils | 1.6 |
| JUnit | 3.8.1 |
| 构建工具 | Maven 3 |
| Scala Maven Plugin | 4.8.1 |
| Maven Assembly Plugin | 3.7.1 |
项目 `pom.xml` 当前固定使用 **Java 8 + Scala 2.11.12 + Spark 2.4.3**,因此建议使用对应版本的 JDK 和依赖环境。
---
## 项目结构
```text
spark_20260915/
├── pom.xml
├── README.md
├── AGENTS.md
│
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/example/
│ │ │ └── core/
│ │ │ ├── GroupByKeyDemo.java
│ │ │ ├── MyPartitioner.java
│ │ │ ├── RddCreateDemo.java
│ │ │ └── RepartitionVsCoalesce.java
│ │ │
│ │ ├── scala/
│ │ │ └── org/
│ │ │ ├── example/
│ │ │ │ ├── App.scala
│ │ │ │ ├── test.scala
│ │ │ │ ├── core/
│ │ │ │ └── sql/
│ │ │ │
│ │ │ └── exercises/
│ │ │ ├── exercises1/
│ │ │ ├── exercises2/
│ │ │ ├── exercises3/
│ │ │ ├── exercises4/
│ │ │ └── exercises5/
│ │ │
│ │ └── resources/
│ │ ├── log4j.properties
│ │ ├── word.txt
│ │ └── create_table.sql
│ │
│ └── test/
│ └── java/
│
└── target/
```
### 目录说明
#### `org/example`
主要存放课程外的 Demo、线下课程代码以及一些完整示例。
其中:
```text
org/example/core/
```
主要用于演示 Spark Core 基础功能,包括:
- RDD 创建
- `groupByKey`
- 自定义 `Partitioner`
- `repartition`
- `coalesce`
同时存在 Java 与 Scala 两套实现,用于对比两种语言编写 Spark 程序的方式。
```text
org/example/sql/
```
用于存放 Spark SQL / DataFrame 相关示例,例如通过 `SparkSession` 创建 DataFrame。
---
#### `org/exercises`
这是本项目最核心的学习目录。
每一课按照课程编号划分:
```text
exercises1
exercises2
exercises3
exercises4
exercises5
```
通常将:
```text
demo/
```
用于课程演示代码,
```text
exercises/
```
用于自己完成的课后练习。
这样可以把“看懂 Demo”和“自己写代码”区分开。
---
# 课程进度
## 第 1 课:Spark 是什么,以及第一个 Spark 程序
目录:
```text
src/main/scala/org/exercises/exercises1/
```
主要学习:
- Spark 的基本概念
- `SparkConf`
- `SparkContext`
- 本地模式 `local`
- 从集合创建 RDD
- 从文件创建 RDD
- Transformation
- Action
- 第一个 WordCount
这一课的目标是先建立 Spark 程序的整体结构。
---
## 第 2 课:RDD 常用算子
目录:
```text
src/main/scala/org/exercises/exercises2/
```
重点学习单值 RDD 的常见操作:
| 练习 | 内容 |
| --- | --- |
| Ex 1 | `map` |
| Ex 2 | `filter` |
| Ex 3 | `flatMap` |
| Ex 4 | `reduce` |
| Ex 5 | `foreach` |
通过这些练习理解:
```text
RDD
↓
Transformation
↓
Action
```
并逐渐熟悉 Scala 函数、匿名函数以及 Spark 算子的使用方式。
---
## 第 3 课:PairRDD 与 reduceByKey
目录:
```text
src/main/scala/org/exercises/exercises3/
```
重点学习:
- `(K, V)` 类型的 PairRDD
- `map`
- `reduceByKey`
- WordCount
核心代码结构:
```scala
rdd
.flatMap(...)
.map(...)
.reduceByKey(...)
.collect()
```
这一课开始正式进入 Spark 中非常重要的 **Key-Value 数据处理模式**。
---
## 第 4 课:groupByKey、reduceByKey 与 Shuffle
目录:
```text
src/main/scala/org/exercises/exercises4/
```
重点学习:
- `groupByKey`
- `reduceByKey`
- Shuffle
- Map 端局部聚合
- 宽依赖与窄依赖
- 为什么 `reduceByKey` 通常比直接 `groupByKey` 更适合做聚合计算
通过实际 Demo 对比:
```text
groupByKey
```
和:
```text
reduceByKey
```
的数据处理过程,理解 Shuffle 在 Spark 中到底发生了什么。
---
## 第 5 课:Partition 分区
目录:
```text
src/main/scala/org/exercises/exercises5/
```
主要学习 Spark RDD 的分区机制。
重点内容:
- `getNumPartitions`
- `glom`
- RDD 分区查看
- `repartition`
- `coalesce`
- `partitionBy`
- 自定义 `Partitioner`
- Key 到 Partition 的映射
例如自定义分区器:
```scala
class MyPartitioner extends Partitioner {
override def numPartitions: Int = 2
override def getPartition(key: Any): Int = {
key.asInstanceOf[Int] % 2
}
}
```
通过代码理解:
```text
RDD
↓
Partition
↓
Task
```
以及 Key 如何决定数据最终进入哪个 Partition。
当前仓库 `main` 分支最新提交已经进入这一课。
---
# 线下课程 Demo
除了 ChatGPT 分课练习之外,仓库还保留了一些线下课程代码,用于补充 Spark 实际开发中的知识。
## RDD 创建、操作与重分区
主要涉及:
- RDD 创建
- RDD Transformation
- RDD Action
- `repartition`
- `coalesce`
- Partition
---
## Cache / Persist / Checkpoint
用于理解 Spark 中的数据持久化机制,包括:
- `cache()`
- `persist()`
- `checkpoint()`
- Checkpoint 目录
- RDD 血缘关系
- 长依赖链优化
同时包含 Spark 程序打包以及向 YARN 提交运行的相关学习内容。
---
## Spark SQL / DataFrame
目录:
```text
src/main/scala/org/example/sql/
```
当前已有 DataFrame 创建示例,通过:
```scala
SparkSession
```
创建 Spark 应用,然后:
```scala
import spark.implicits._
val df = data.toDF()
df.show()
df.printSchema()
```
用于学习:
- `SparkSession`
- DataFrame
- `toDF`
- `show`
- `printSchema`
当前仓库已经包含对应的 DataFrame Demo。
---
# WordCount
项目中多处使用 WordCount 作为学习案例。
典型流程:
```text
文本
↓
flatMap
↓
拆分单词
↓
map
↓
(word, 1)
↓
reduceByKey
↓
统计单词数量
```
Scala 示例:
```scala
val result = textFile
.flatMap(_.split(" "))
.map(word => (word, 1))
.reduceByKey(_ + _)
```
WordCount 看起来简单,但可以贯穿整个 Spark 学习过程:
```text
RDD
↓
Transformation
↓
PairRDD
↓
reduceByKey
↓
Shuffle
↓
Partition
```
因此本项目会反复使用 WordCount 来帮助理解 Spark 的底层处理过程。
---
# Maven 构建
## 拉取依赖
```bash
mvn -DskipTests dependency:resolve
```
## 编译
```bash
mvn compile
```
## 测试
```bash
mvn test
```
目前测试目录主要用于预留,随着课程推进逐步补充测试。
## 打包
```bash
mvn package
```
完成后会生成:
```text
target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar
```
项目目前使用 `scala-maven-plugin` 编译 Scala,并使用 `maven-assembly-plugin` 打包包含依赖的 Fat JAR。
---
# 运行程序
## IntelliJ IDEA
推荐直接在 IntelliJ IDEA 中运行。
打开:
```text
pom.xml
```
等待 Maven 加载完成后,可以直接找到带有:
```scala
def main(args: Array[String]): Unit
```
的 Scala `object` 运行。
例如:
```text
org.example.App
```
或者:
```text
org.exercises.exercises5.demo.Demo
```
具体运行哪个类,根据当前学习章节选择即可。
---
## 命令行运行 Fat JAR
例如:
```bash
java -cp target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar org.example.App
```
项目主要用于本地学习和实验,不要求先搭建真正的 Spark 集群。
---
# 学习方式
本项目建议按照下面的方式学习:
```text
先看 Demo
↓
理解代码
↓
自己完成 Exercises
↓
运行并观察结果
↓
修改代码验证结论
↓
记录到 Git
```
尤其是学习 Spark 时,不建议只看最终输出。
例如学习 Partition 时,可以通过:
```scala
rdd.getNumPartitions
rdd.glom().collect()
```
直接观察不同 Partition 中的数据。
学习 Shuffle 时,则重点观察:
```text
数据在不同 Partition 之间如何重新分布
```
这样比单纯记住 API 更容易真正理解 Spark。
---
# Git 提交规范
当前项目采用简洁的中文 Commit Message。
推荐格式:
```text
feat:ChatGPT 第 X 课:课程主题
```
例如:
```text
feat:ChatGPT 第 1 课:Spark 是什么,以及第一个 Spark 程序
feat:ChatGPT 第 2 课:RDD 常用算子
feat:ChatGPT 第 3 课:PairRDD 与 reduceByKey
feat:ChatGPT 第 4 课:groupByKey、reduceByKey 与 Shuffle
feat:ChatGPT 第 5 课:Partition 分区
```
其他类型:
```text
docs:README
build:更新 Maven 依赖
```
建议一节课一个主要 Commit,一道独立练习尽量保持原子提交。
---
# 开发约定
### Java / Scala
项目同时保留 Java 和 Scala 两套实现。
学习阶段以 Scala 为主,Java Demo 主要用于:
- 对照 Spark API
- 理解 Java 与 Scala 的写法差异
- 复习 Spark 基础 API
新课程练习优先使用 Scala。
### Spark 模式
学习阶段主要使用:
```scala
.setMaster("local")
```
或者:
```scala
.setMaster("local[2]")
```
部分 DataFrame Demo 使用本地多线程模式。
整个项目定位是:
> **本地 Spark 学习、实验与知识整理仓库**
而不是生产环境 Spark 项目。
---
# MySQL / JDBC 扩展
项目 Maven 依赖中已经包含:
- MySQL Connector
- HikariCP
- commons-dbutils
资源目录中也保留:
```text
src/main/resources/create_table.sql
```
用于后续 Spark 数据处理结果写入 MySQL 的实验。
后续可以继续完善:
```text
Spark
↓
RDD / DataFrame
↓
数据分析
↓
JDBC
↓
MySQL
```
逐步从 Spark 基础练习过渡到实际的数据处理流程。
---
# 当前学习进度
```text
✅ 第 1 课:Spark 入门
✅ 第 2 课:RDD 常用算子
✅ 第 3 课:PairRDD 与 reduceByKey
✅ 第 4 课:groupByKey、reduceByKey 与 Shuffle
✅ 第 5 课:Partition 分区
✅ 线下课:RDD 创建 / 操作 / 重分区
✅ 线下课:Cache / Persist / Checkpoint
✅ 线下课:Spark 程序打包 / YARN
✅ 线下课:创建 DataFrame
⬜ 后续课程:继续学习 Spark Core
⬜ 后续课程:Spark SQL / DataFrame 深入
⬜ 后续课程:真实数据分析案例
```
---
# 后续规划
后续按照课程继续补充:
```text
Spark Core
↓
RDD
↓
Shuffle
↓
Partition
↓
持久化
↓
广播变量 / 累加器
↓
Spark SQL
↓
DataFrame
↓
数据分析案例
↓
MySQL / JDBC
```
项目会尽量保持:
- 一课一目录
- Demo 与 Exercises 分离
- 代码可以直接运行
- 中文注释辅助理解
- 每个知识点配合实际输出验证
- 用 Git 记录学习进度
---
## 项目定位
这是一个以 **“边学、边写、边运行、边总结”** 为核心的 Spark 学习仓库。
相比只保存课堂代码,本项目更关注:
```text
为什么这么写
↓
代码实际做了什么
↓
Spark 底层发生了什么
↓
运行结果为什么是这样
```
通过持续增加 Demo 和练习,将 Spark 的知识点逐渐串联起来,形成一套完整的个人学习笔记与实践代码库。