docs:README
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
`spark_project` — Spark(Scala + Java 双实现)学习项目,含三套分层练习与 MySQL 写入示例表。
|
||||||
|
|
||||||
|
## Setup commands
|
||||||
|
|
||||||
|
- 拉依赖:`mvn -DskipTests dependency:resolve`
|
||||||
|
- 编译:`mvn compile`(同时编译 `src/main/java` 与 `src/main/scala`)
|
||||||
|
- 打包:`mvn package`(产出 `target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar`)
|
||||||
|
- 跑测试:`mvn test`(当前 `src/test/` 为空,等价空跑)
|
||||||
|
- 清理:`mvn clean`
|
||||||
|
- 单文件运行入口:IDE 里把目标 `object ExercisesX` / `class Xxx` 作为 `main` 直接 run,或:
|
||||||
|
`java -cp target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar org.example.App`
|
||||||
|
|
||||||
|
## Project layout
|
||||||
|
|
||||||
|
- `pom.xml` — Maven 配置,启用 `scala-maven-plugin` 与 `maven-assembly-plugin`,强制 JDK 8 / Scala 2.11
|
||||||
|
- `src/main/java/org/example/core/` — Java 版 4 个核心 Demo(`GroupByKeyDemo` / `MyPartitioner` / `RddCreateDemo` / `RepartitionVsCoalesce`)
|
||||||
|
- `src/main/scala/org/example/App.scala` — Scala 入口(`local[2]` 模式跑 `word.txt` WordCount)
|
||||||
|
- `src/main/scala/org/example/core/` — 与 Java 同名的 Scala 版 4 个 Demo
|
||||||
|
- `src/main/scala/org/exercises/exercises1/exercises/` — 第 1 课练习(Spark 入门)
|
||||||
|
- `src/main/scala/org/exercises/exercises2/exercises/` — 第 2 课练习(RDD 算子:map / filter / flatMap / reduce / foreach)
|
||||||
|
- `src/main/scala/org/exercises/exercises3/exercises/` — 第 3 课练习(PairRDD / reduceByKey / WordCount)
|
||||||
|
- `src/main/scala/org/exercises/exercisesN/demo/` — 上述练习对应的演示实现
|
||||||
|
- `src/main/resources/` — `log4j.properties` / `word.txt` / MySQL 建表 SQL `create_table.sql`
|
||||||
|
- `src/test/java/` — 测试目录(JUnit 3.8.1 已声明但当前为空)
|
||||||
|
|
||||||
|
## Code style
|
||||||
|
|
||||||
|
- Java 8(`maven.compiler.source/target=8`)与 Scala 2.11.12 共存;新文件优先 Scala,统一参考现有 demo 的写法
|
||||||
|
- Spark Master 全部固定为 `local` / `local[2]`,本机调试无需集群
|
||||||
|
- 中文注释和**中文 commit message** 是项目常态(参考最近 6 个 commit),不要切换成英文
|
||||||
|
|
||||||
|
## Testing instructions
|
||||||
|
|
||||||
|
- 当前 `src/test/` 没有任何用例,跑测试等价于空跑
|
||||||
|
- 加测试用 `src/test/java/`,包路径跟随被测包(`org.example` / `org.exercises.xxx`),JUnit 3.8.1(继承 `TestCase`,方法名 `testXxx`)
|
||||||
|
- 所有测试通过后再提 PR
|
||||||
|
|
||||||
|
## PR & commit conventions
|
||||||
|
|
||||||
|
- 默认分支:`main`,从 `main` 拉 feature 分支,**禁止直接 push 到 `main`**
|
||||||
|
- Commit 风格:参考现有 `feat:ChatGPT 第 X 课:主题` 形式,保持**简体中文 + 一句话主题**
|
||||||
|
- 单节课 / 单道练习的提交保持原子;本仓库暂无 CI(`.github/workflows/` 未配置),提 PR 前请本地跑通 `mvn test`
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- `.gitignore` 已忽略 `target/`、`.idea/`、`*.iml`、`.classpath` 等构建 / IDE 产物
|
||||||
|
- MySQL / Hadoop 凭据**不要**写进 `src/main/resources/`,需要外部化(环境变量或 `*.local.properties`,并加入 `.gitignore`)
|
||||||
|
- 不要把含个人 token 的 fat jar 提交到仓库
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
# Spark 学习项目(spark_project)
|
||||||
|
|
||||||
|
跟着 ChatGPT 课程的 Spark 学习笔记,用 **Scala + Java 双实现** 覆盖 Spark Core 的 RDD 基础、PairRDD、WordCount,并通过 MySQL 写入的示例表把练习串成一个迷你数仓案例。
|
||||||
|
|
||||||
|
> 课程三讲(一→三)一→一对应当前 `src/main/scala/org/exercises/exercises{1,2,3}` 三套练习;另有「线下课:RDD 创建/操作/重分区」的一份 Java 版 Demo。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
| 类别 | 版本 |
|
||||||
|
| ---------- | ------------------------------------------ |
|
||||||
|
| JVM | Java 8 |
|
||||||
|
| 语言 | Scala 2.11.12 + Java 8(双实现) |
|
||||||
|
| 计算引擎 | Apache Spark 2.4.3(core + sql) |
|
||||||
|
| 分布式 | Hadoop Client 2.7.3 |
|
||||||
|
| 数据库 | MySQL 8.0.28 |
|
||||||
|
| 连接池 | HikariCP 4.0.3 |
|
||||||
|
| JDBC 工具 | commons-dbutils 1.6 |
|
||||||
|
| 测试 | JUnit 3.8.1 |
|
||||||
|
| 构建 | Maven 3 + scala-maven-plugin 4.8.1 + maven-assembly-plugin 3.7.1 |
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
spark_project/
|
||||||
|
├── pom.xml # Maven 配置(强制 JDK 8 / Scala 2.11)
|
||||||
|
├── src/main/java/org/example/
|
||||||
|
│ ├── core/
|
||||||
|
│ │ ├── GroupByKeyDemo.java # Java 版 4 个核心 Demo
|
||||||
|
│ │ ├── MyPartitioner.java
|
||||||
|
│ │ ├── RddCreateDemo.java
|
||||||
|
│ │ └── RepartitionVsCoalesce.java
|
||||||
|
│ └── AppTest.java # JUnit 默认骨架
|
||||||
|
├── src/main/scala/org/example/
|
||||||
|
│ ├── App.scala # Scala 入口:local[2] 模式 + word.txt WordCount
|
||||||
|
│ ├── test.scala
|
||||||
|
│ └── core/ # Scala 版同名 4 个 Demo
|
||||||
|
│ ├── GroupByKeyDemo.scala
|
||||||
|
│ ├── MyPartitioner.scala
|
||||||
|
│ ├── RddCreateDemo.scala
|
||||||
|
│ └── RepartitionVsCoalesce.scala
|
||||||
|
├── src/main/scala/org/exercises/
|
||||||
|
│ ├── exercises1/ # 第 1 课:Spark 入门
|
||||||
|
│ │ ├── demo/ # 演示 Demo1~5
|
||||||
|
│ │ └── exercises/Exercises1..5.scala # 课后 5 题(题目以中文注释形式嵌入文件头)
|
||||||
|
│ ├── exercises2/ # 第 2 课:RDD 算子(map / filter / flatMap / reduce / foreach)
|
||||||
|
│ └── exercises3/ # 第 3 课:PairRDD / reduceByKey / WordCount
|
||||||
|
└── src/main/resources/
|
||||||
|
├── create_table.sql # MySQL:Top10 平均评分电影 + 类别平均评分
|
||||||
|
├── log4j.properties
|
||||||
|
└── word.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速上手
|
||||||
|
|
||||||
|
### 1. 准备环境
|
||||||
|
|
||||||
|
- **JDK 8**(`pom.xml` 已锁定 `maven.compiler.source/target=8`,高版本会编译失败)
|
||||||
|
- **Maven 3.6+**(仓库根目录留有 `.mvn/`,但还没生成 `mvnw`,自行安装一个 `mvn` 到 `PATH` 即可)
|
||||||
|
- 一台能跑 `local` / `local[2]` 模式的机器即可,**不需要真正的 Spark 集群**
|
||||||
|
|
||||||
|
### 2. 编译与打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1) 拉依赖
|
||||||
|
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
|
||||||
|
java -cp target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar \
|
||||||
|
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,主题风格统一为**简体中文 + 简短摘要**:
|
||||||
|
|
||||||
|
```
|
||||||
|
feat:ChatGPT 第 1 课:Spark 是什么,以及第一个 Spark 程序
|
||||||
|
feat:ChatGPT 第 2 课:RDD 常用算子
|
||||||
|
feat:ChatGPT 第 3 课:PairRDD 与 reduceByKey
|
||||||
|
线下课:RDD的创建、RDD的操作、RDD重分区
|
||||||
|
feat:首次提交
|
||||||
|
```
|
||||||
|
|
||||||
|
继续沿用 `feat:<主题>` 形式,**中文一句话主题**,变更保持原子(新题 / 新课一个 commit)。默认分支 `main`,从 `main` 拉 feature 分支再合,禁止直接 push。
|
||||||
|
|
||||||
|
## 安全约定
|
||||||
|
|
||||||
|
- `target/`、`.idea/`、`*.iml` 等构建/IDE 产物已在 `.gitignore`
|
||||||
|
- **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 版本
|
||||||
Reference in New Issue
Block a user