docs:更新README
This commit is contained in:
@@ -1,179 +1,753 @@
|
|||||||
# Spark 学习项目(spark_project)
|
# Spark 学习项目
|
||||||
|
|
||||||
跟着 ChatGPT 课程的 Spark 学习笔记,用 **Scala + Java 双实现** 覆盖 Spark Core 的 RDD 基础、PairRDD、WordCount,并通过 MySQL 写入的示例表把练习串成一个迷你数仓案例。
|
基于 **Scala + Java** 的 Apache Spark 学习与练习项目。
|
||||||
|
|
||||||
> 课程三讲(一→三)一→一对应当前 `src/main/scala/org/exercises/exercises{1,2,3}` 三套练习;另有「线下课:RDD 创建/操作/重分区」的一份 Java 版 Demo。
|
本项目主要用于个人学习和记录 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 提交
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
| 类别 | 版本 |
|
| 技术 | 版本 / 说明 |
|
||||||
| ---------- | ------------------------------------------ |
|
| --- | --- |
|
||||||
| JVM | Java 8 |
|
| JDK | 8 |
|
||||||
| 语言 | Scala 2.11.12 + Java 8(双实现) |
|
| Scala | 2.11.12 |
|
||||||
| 计算引擎 | Apache Spark 2.4.3(core + sql) |
|
| Apache Spark | 2.4.3 |
|
||||||
| 分布式 | Hadoop Client 2.7.3 |
|
| Hadoop Client | 2.7.3 |
|
||||||
| 数据库 | MySQL 8.0.28 |
|
| MySQL | 8.0.28 |
|
||||||
| 连接池 | HikariCP 4.0.3 |
|
| HikariCP | 4.0.3 |
|
||||||
| JDBC 工具 | commons-dbutils 1.6 |
|
| commons-dbutils | 1.6 |
|
||||||
| 测试 | JUnit 3.8.1 |
|
| JUnit | 3.8.1 |
|
||||||
| 构建 | Maven 3 + scala-maven-plugin 4.8.1 + maven-assembly-plugin 3.7.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_project/
|
spark_20260915/
|
||||||
├── pom.xml # Maven 配置(强制 JDK 8 / Scala 2.11)
|
├── pom.xml
|
||||||
├── src/main/java/org/example/
|
├── README.md
|
||||||
│ ├── core/
|
├── AGENTS.md
|
||||||
│ │ ├── GroupByKeyDemo.java # Java 版 4 个核心 Demo
|
│
|
||||||
│ │ ├── MyPartitioner.java
|
├── src/
|
||||||
│ │ ├── RddCreateDemo.java
|
│ ├── main/
|
||||||
│ │ └── RepartitionVsCoalesce.java
|
│ │ ├── java/
|
||||||
│ └── AppTest.java # JUnit 默认骨架
|
│ │ │ └── org/example/
|
||||||
├── src/main/scala/org/example/
|
│ │ │ └── core/
|
||||||
│ ├── App.scala # Scala 入口:local[2] 模式 + word.txt WordCount
|
│ │ │ ├── GroupByKeyDemo.java
|
||||||
│ ├── test.scala
|
│ │ │ ├── MyPartitioner.java
|
||||||
│ └── core/ # Scala 版同名 4 个 Demo
|
│ │ │ ├── RddCreateDemo.java
|
||||||
│ ├── GroupByKeyDemo.scala
|
│ │ │ └── RepartitionVsCoalesce.java
|
||||||
│ ├── MyPartitioner.scala
|
│ │ │
|
||||||
│ ├── RddCreateDemo.scala
|
│ │ ├── scala/
|
||||||
│ └── RepartitionVsCoalesce.scala
|
│ │ │ └── org/
|
||||||
├── src/main/scala/org/exercises/
|
│ │ │ ├── example/
|
||||||
│ ├── exercises1/ # 第 1 课:Spark 入门
|
│ │ │ │ ├── App.scala
|
||||||
│ │ ├── demo/ # 演示 Demo1~5
|
│ │ │ │ ├── test.scala
|
||||||
│ │ └── exercises/Exercises1..5.scala # 课后 5 题(题目以中文注释形式嵌入文件头)
|
│ │ │ │ ├── core/
|
||||||
│ ├── exercises2/ # 第 2 课:RDD 算子(map / filter / flatMap / reduce / foreach)
|
│ │ │ │ └── sql/
|
||||||
│ └── exercises3/ # 第 3 课:PairRDD / reduceByKey / WordCount
|
│ │ │ │
|
||||||
└── src/main/resources/
|
│ │ │ └── exercises/
|
||||||
├── create_table.sql # MySQL:Top10 平均评分电影 + 类别平均评分
|
│ │ │ ├── exercises1/
|
||||||
├── log4j.properties
|
│ │ │ ├── exercises2/
|
||||||
└── word.txt
|
│ │ │ ├── exercises3/
|
||||||
|
│ │ │ ├── exercises4/
|
||||||
|
│ │ │ └── exercises5/
|
||||||
|
│ │ │
|
||||||
|
│ │ └── resources/
|
||||||
|
│ │ ├── log4j.properties
|
||||||
|
│ │ ├── word.txt
|
||||||
|
│ │ └── create_table.sql
|
||||||
|
│ │
|
||||||
|
│ └── test/
|
||||||
|
│ └── java/
|
||||||
|
│
|
||||||
|
└── target/
|
||||||
```
|
```
|
||||||
|
|
||||||
## 快速上手
|
### 目录说明
|
||||||
|
|
||||||
### 1. 准备环境
|
#### `org/example`
|
||||||
|
|
||||||
- **JDK 8**(`pom.xml` 已锁定 `maven.compiler.source/target=8`,高版本会编译失败)
|
主要存放课程外的 Demo、线下课程代码以及一些完整示例。
|
||||||
- **Maven 3.6+**(仓库根目录留有 `.mvn/`,但还没生成 `mvnw`,自行安装一个 `mvn` 到 `PATH` 即可)
|
|
||||||
- 一台能跑 `local` / `local[2]` 模式的机器即可,**不需要真正的 Spark 集群**
|
|
||||||
|
|
||||||
### 2. 编译与打包
|
其中:
|
||||||
|
|
||||||
|
```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
|
```bash
|
||||||
# 1) 拉依赖
|
|
||||||
mvn -DskipTests dependency:resolve
|
mvn -DskipTests dependency:resolve
|
||||||
|
|
||||||
# 2) 编译(Scala + Java 同时)
|
|
||||||
mvn compile
|
|
||||||
|
|
||||||
# 3) 跑测试(当前 src/test/ 仍为空,等价于空跑)
|
|
||||||
mvn test
|
|
||||||
|
|
||||||
# 4) 打 fat jar(含 Spark / Hadoop / MySQL 等所有依赖)
|
|
||||||
mvn package
|
|
||||||
|
|
||||||
# 5) 产出路径
|
|
||||||
ls target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 跑一个 Scala 入口
|
## 编译
|
||||||
|
|
||||||
两种方式二选一:
|
|
||||||
|
|
||||||
**方式 A:IDE 直跑**。在 IntelliJ IDEA 里直接打开 `pom.xml`,把以下任一对象作为 `main` 入口运行:
|
|
||||||
|
|
||||||
- `org.example.App` — `local[2]` 模式读 `src/main/resources/word.txt`,做一次 `count + filter + flatMap → reduceByKey` 的 WordCount
|
|
||||||
- `org.exercises.exercises3.exercises.Exercises5` — 纯数据集合版 WordCount(输出 `hello=3, spark=3, scala=1, is=1, powerful=1`)
|
|
||||||
|
|
||||||
**方式 B:命令行跑 fat jar**。
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
java -cp target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar \
|
mvn compile
|
||||||
org.example.App
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> 默认 `pom.xml` 没配 `exec-maven-plugin`,所以 `mvn exec:java` 用不了,要么走方式 A,要么上 fat jar。
|
## 测试
|
||||||
|
|
||||||
## 三套练习索引
|
|
||||||
|
|
||||||
### `exercises1` — 第 1 课:Spark 是什么,以及第一个 Spark 程序
|
|
||||||
|
|
||||||
源:`src/main/scala/org/exercises/exercises1/`
|
|
||||||
主题:`SparkConf` / `SparkContext` 创建、并行化集合、读取外部文件。
|
|
||||||
代表题:
|
|
||||||
|
|
||||||
| 编号 | 题目要点 |
|
|
||||||
| ----- | ------------------------------------------------- |
|
|
||||||
| Ex 1 | 搭一个 `SparkContext`,`setMaster("local")` |
|
|
||||||
| Ex 2 | 从本地/集合源构造 RDD |
|
|
||||||
| Ex 3 | 基础转换算子 |
|
|
||||||
| Ex 4 | 触发动作算子 |
|
|
||||||
| Ex 5 | 综合:第一个本地 WordCount |
|
|
||||||
|
|
||||||
### `exercises2` — 第 2 课:RDD 常用算子
|
|
||||||
|
|
||||||
源:`src/main/scala/org/exercises/exercises2/`
|
|
||||||
主题:单值 RDD 的转换与动作。
|
|
||||||
|
|
||||||
| 编号 | 算子 |
|
|
||||||
| ----- | ------------ |
|
|
||||||
| Ex 1 | `map` |
|
|
||||||
| Ex 2 | `filter` |
|
|
||||||
| Ex 3 | `flatMap` |
|
|
||||||
| Ex 4 | `reduce` |
|
|
||||||
| Ex 5 | `foreach` |
|
|
||||||
|
|
||||||
### `exercises3` — 第 3 课:PairRDD 与 reduceByKey
|
|
||||||
|
|
||||||
源:`src/main/scala/org/exercises/exercises3/`
|
|
||||||
主题:键值对 RDD 常用算子与正式 WordCount。
|
|
||||||
|
|
||||||
| 编号 | 算子 / 内容 |
|
|
||||||
| ----- | -------------------------------------------------------- |
|
|
||||||
| Ex 5 | 正式练 WordCount:`flatMap → map → reduceByKey → collect` |
|
|
||||||
|
|
||||||
> `exercises1/2/3/demo/` 目录下还有 5 个对应演示,可在写练习前打开当作参考实现。
|
|
||||||
|
|
||||||
## MySQL 结果表
|
|
||||||
|
|
||||||
`src/main/resources/create_table.sql` 里两张表是后续评分分析的目标输出:
|
|
||||||
|
|
||||||
| 表名 | 主用途 |
|
|
||||||
| -------------------------- | ---------------------------------- |
|
|
||||||
| `top_ten_avg_ratings` | TopN 平均评分电影(`movie_id` 唯一) |
|
|
||||||
| `genres_average_rating` | 类型平均评分(`genres` 唯一) |
|
|
||||||
|
|
||||||
依赖侧(`pom.xml`)已经预备好:
|
|
||||||
|
|
||||||
- `mysql-connector-java` 8.0.28
|
|
||||||
- `HikariCP` 4.0.3
|
|
||||||
- `commons-dbutils` 1.6
|
|
||||||
|
|
||||||
下一步只要写真实的 Spark SQL / DataFrame → JDBC 写入逻辑即可。使用前请在 MySQL 里先执行 `create_table.sql`。
|
|
||||||
|
|
||||||
## 提交规范
|
|
||||||
|
|
||||||
仓库已有 6 条 commit,主题风格统一为**简体中文 + 简短摘要**:
|
|
||||||
|
|
||||||
|
```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 第 1 课:Spark 是什么,以及第一个 Spark 程序
|
||||||
feat:ChatGPT 第 2 课:RDD 常用算子
|
feat:ChatGPT 第 2 课:RDD 常用算子
|
||||||
feat:ChatGPT 第 3 课:PairRDD 与 reduceByKey
|
feat:ChatGPT 第 3 课:PairRDD 与 reduceByKey
|
||||||
线下课:RDD的创建、RDD的操作、RDD重分区
|
feat:ChatGPT 第 4 课:groupByKey、reduceByKey 与 Shuffle
|
||||||
feat:首次提交
|
feat:ChatGPT 第 5 课:Partition 分区
|
||||||
```
|
```
|
||||||
|
|
||||||
继续沿用 `feat:<主题>` 形式,**中文一句话主题**,变更保持原子(新题 / 新课一个 commit)。默认分支 `main`,从 `main` 拉 feature 分支再合,禁止直接 push。
|
其他类型:
|
||||||
|
|
||||||
## 安全约定
|
```text
|
||||||
|
docs:README
|
||||||
|
build:更新 Maven 依赖
|
||||||
|
```
|
||||||
|
|
||||||
- `target/`、`.idea/`、`*.iml` 等构建/IDE 产物已在 `.gitignore`
|
建议一节课一个主要 Commit,一道独立练习尽量保持原子提交。
|
||||||
- **MySQL / Hadoop 凭据**一律外部化(环境变量或 `*.local.properties`,并加入 `.gitignore`),不要写进 `src/main/resources/`
|
|
||||||
- 不要把含个人 token 的 fat jar 提交到仓库
|
|
||||||
|
|
||||||
## 下一步
|
---
|
||||||
|
|
||||||
- [ ] `src/test/` 仍为空,按练习补 JUnit 3 测试用例
|
# 开发约定
|
||||||
- [ ] 把 Spark SQL/DataFrame 的分析结果真正写回 `top_ten_avg_ratings`、`genres_average_rating`
|
|
||||||
- [ ] 加一份 `.mvn/wrapper/maven-wrapper.properties` 让团队对齐 Maven 版本
|
### 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 的知识点逐渐串联起来,形成一套完整的个人学习笔记与实践代码库。
|
||||||
Reference in New Issue
Block a user