# 导读：一套电商实时数仓的教学全景

> 从整体定位仓库：三个 Maven 工程各司其职，实时模块按数仓分层组织代码，两个发布工程负责把结果查询出来做可视化。作为开篇，先建立模块边界与技术栈印象，再给出从架构、数据流、计算存储、系统优化到业务实现的阅读路线，避免与后续各页重复。

- Repository: aggaadfr/gmall-flink-3.0
- GitHub: https://github.com/aggaadfr/gmall-flink-3.0
- Human wiki: https://grok-wiki.com/public/wiki/aggaadfr-gmall-flink-3-0-446e0d5adb69
- Complete Markdown: https://grok-wiki.com/public/wiki/aggaadfr-gmall-flink-3-0-446e0d5adb69/llms-full.txt

## Source Files

- `README.md`
- `pom.xml`
- `gmall-realtime/pom.xml`
- `gmall-publisher-2022/pom.xml`

---

<details>
<summary>相关源文件</summary>
以下文件用于生成此维基页面：
- [README.md](README.md)
- [pom.xml](pom.xml)
- [gmall-realtime/pom.xml](gmall-realtime/pom.xml)
- [gmall-realtime/src/main/java/com/atguigu/app/dim/DimApp.java](gmall-realtime/src/main/java/com/atguigu/app/dim/DimApp.java)
- [gmall-realtime/src/main/java/com/atguigu/app/func/DimSinkFunction.java](gmall-realtime/src/main/java/com/atguigu/app/func/DimSinkFunction.java)
- [gmall-realtime/src/main/java/com/atguigu/app/dwd/log/BaseLogApp.java](gmall-realtime/src/main/java/com/atguigu/app/dwd/log/BaseLogApp.java)
- [gmall-realtime/src/main/java/com/atguigu/app/dws/DwsTrafficPageViewWindow.java](gmall-realtime/src/main/java/com/atguigu/app/dws/DwsTrafficPageViewWindow.java)
- [gmall-realtime/src/main/java/com/atguigu/utils/ClickHouseUtil.java](gmall-realtime/src/main/java/com/atguigu/utils/ClickHouseUtil.java)
- [gmall-realtime/src/main/java/com/atguigu/utils/DimUtil.java](gmall-realtime/src/main/java/com/atguigu/utils/DimUtil.java)
- [gmall-realtime/src/main/java/com/atguigu/common/GmallConfig.java](gmall-realtime/src/main/java/com/atguigu/common/GmallConfig.java)
- [gmall-publisher/pom.xml](gmall-publisher/pom.xml)
- [gmall-publisher-2022/pom.xml](gmall-publisher-2022/pom.xml)
- [gmall-publisher-2022/src/main/java/com/atguigu/gmall/publisher/controller/TrafficController.java](gmall-publisher-2022/src/main/java/com/atguigu/gmall/publisher/controller/TrafficController.java)
</details>

# 导读：一套电商实时数仓的教学全景

这个仓库是一份电商实时数仓的教学项目（Flink 版本 3.0），它的价值不在于业务复杂度，而在于把一套真实企业级数仓的**分层思想**压缩到了三个 Maven 工程里。读懂仓库之前，先看清三件事：谁在算、结果存到哪、谁把结果查出来。

本页只做“地图”工作：建立模块边界、技术栈与阅读顺序的印象，把「架构、数据流、计算存储、系统优化、业务实现」这五类话题指到正确的入口，避免与后续各页重复展开。

## 一个父工程，三个 Maven 模块

根 `pom.xml` 只是聚合壳，打包方式为 `pom`，声明了三个子模块与 Java 8 编译目标（[pom.xml:7-20](pom.xml)）。README 用一句话概括了分工（[README.md:24-31](README.md)）：

```
gmall-flink-3.0
├── gmall-publisher         测试数据可视化接口（实验版）
├── gmall-publisher-2022    完成数据可视化接口（完整版）
└── gmall-realtime          实时模块
```

三者定位差异很大，是阅读时的第一把钥匙：

| 模块 | 形态 | 职责 | 技术底座 |
| --- | --- | --- | --- |
| `gmall-realtime` | Maven 普通工程，无框架 | 数仓加工：消费 ODS、清洗分流、聚合落库 | Flink 1.13 + 各类连接器 |
| `gmall-publisher` | Spring Boot 2.4 | 可视化查询的实验版（GMV/UV 两个指标） | Web + MyBatis + ClickHouse JDBC |
| `gmall-publisher-2022` | Spring Boot 2.6.6 | 覆盖各业务域的完整可视化查询 | Web + MyBatis + ClickHouse JDBC |

注意一个易混淆点：README 称之为「测试数据可视化接口」的 `gmall-publisher` 与「完成数据可视化接口」的 `gmall-publisher-2022` 是**并列的两个发布工程**，不是新旧目录关系——教学上常拿前者做最小验证，后者是完整版。

## gmall-realtime：数仓的“加工车间”

这是仓库主体，59 个 Java 文件集中在 `com.atguigu` 下五个包，包名即分层（`gmall-realtime/src/main/java/com/atguigu/app`）。业务目录只有 `dim`、`dwd`、`dws`、`func` 四个——**没有 ODS 与 ADS 的包**，这两层以不同形态存在：ODS 就是 Kafka 里的原始主题，ADS/展示层则由两个发布工程承担。

Flink 版本统一收敛在 `gmall-realtime/pom.xml` 的属性里（[gmall-realtime/pom.xml:18-20](gmall-realtime/pom.xml)），依赖覆盖了这条教学主线：

- 计算与连接：`flink-java`、`flink-streaming-java`、`flink-connector-kafka`、`flink-json`、`flink-cep`、`flink-table-api` 与 `flink-table-planner-blink`（[gmall-realtime/pom.xml:25-59](gmall-realtime/pom.xml)、[gmall-realtime/pom.xml:142-150](gmall-realtime/pom.xml)）；
- 维表与配置同步：`flink-connector-mysql-cdc` 2.1.0、`mysql-connector-java`、`phoenix-spark` 5.0.0（HBase 2.0）（[gmall-realtime/pom.xml:97-137](gmall-realtime/pom.xml)）；
- 结果存储与关联：`clickhouse-jdbc`、`jedis`、分词器 `ikanalyzer` 等工具（[gmall-realtime/pom.xml:152-179](gmall-realtime/pom.xml)）。

### 包结构与分层对应

| 包/目录 | 对应数仓层 | 落点（Sink） | 典型代表 |
| --- | --- | --- | --- |
| `app/dim` | DIM 维度层 | Phoenix（HBase） | `DimApp` |
| `app/dwd/log` | DWD 流量日志明细 | Kafka 分流主题 | `BaseLogApp` |
| `app/dwd/db` | DWD 业务库明细（交易/工具/互动/用户） | Kafka | `DwdTradeOrderPreProcess` 等 12 个作业 |
| `app/dws` | DWS 汇总层 | ClickHouse | 11 个窗口聚合作业 |
| `app/func` | 通用函数 | — | `TableProcessFunction`、`DimSinkFunction`、异步/关联函数 |
| `bean` / `common` / `utils` | 支撑代码 | — | 数据模型、`GmallConfig`、`MyKafkaUtil` 等 |

**DIM 层**（[DimApp.java:35-80](gmall-realtime/src/main/java/com/atguigu/app/dim/DimApp.java)）体现了教学项目最值得看的设计：消费 Kafka 的 `topic_db`（装着全部业务表的 binlog），用 FlinkCDC 监听 MySQL 里的配置表 `table_process` 生成广播流，按配置动态决定哪些表进维度层；写 Phoenix 时用 `upsert` 动态拼表名与字段（[DimSinkFunction.java:27-52](gmall-realtime/src/main/java/com/atguigu/app/func/DimSinkFunction.java)），更新时先删 Redis 缓存保证一致性。

**DWD 层**以 `BaseLogApp` 为例（[BaseLogApp.java:35](gmall-realtime/src/main/java/com/atguigu/app/dwd/log/BaseLogApp.java)），核心动作是清洗、新老用户校验、再用侧输出流把页面/启动/曝光/动作/错误五类日志分到五个 Kafka 主题（[BaseLogApp.java:100](gmall-realtime/src/main/java/com/atguigu/app/dwd/log/BaseLogApp.java)、[BaseLogApp.java:172-176](gmall-realtime/src/main/java/com/atguigu/app/dwd/log/BaseLogApp.java)）。README 按 15 个主题细述了这层逻辑（[README.md:70-341](README.md)）。

**DWS 层**是窗口聚合，把结果写出到 ClickHouse。落库统一走泛型工具 `ClickHouseUtil.getJdbcSink`（[ClickHouseUtil.java:23-25](gmall-realtime/src/main/java/com/atguigu/utils/ClickHouseUtil.java)），用反射读字段、以 `TransientSink` 注解跳过不需要的字段。例如 `DwsTrafficPageViewWindow` 在头部注释里写明「将数据写出到 ClickHouse」（[DwsTrafficPageViewWindow.java:34-39](gmall-realtime/src/main/java/com/atguigu/app/dws/DwsTrafficPageViewWindow.java)），并在作业末尾调用该工具（[DwsTrafficPageViewWindow.java:202](gmall-realtime/src/main/java/com/atguigu/app/dws/DwsTrafficPageViewWindow.java)）。

存储地址集中在 `GmallConfig`（[GmallConfig.java:12-26](gmall-realtime/src/main/java/com/atguigu/common/GmallConfig.java)）：Phoenix 库 `GMALL211027_REALTIME`、ClickHouse 库 `gmall_211027`，主机是教学集群三节点。

## 两个 publisher：把结果“查”出来做可视化

DWS 写进 ClickHouse 后，剩下的问题就是怎么给大屏提供数据。两个发布工程都是标准的 Spring Boot 三层结构（`controller → service → mapper`），Mapper 层连 ClickHouse 查询预聚合结果；`gmall-publisher-2022` 在 `com.atguigu.gmall.publisher` 下按业务域拆出交易、流量、商品、用户、活动、优惠券六组统计模块（如 [TrafficController.java:17-24](gmall-publisher-2022/src/main/java/com/atguigu/gmall/publisher/controller/TrafficController.java)），并配了一批统计结果 Bean。两个工程都监听 8070 端口、连同一个 ClickHouse 库（[application.properties](gmall-publisher-2022/src/main/resources/application.properties)）。实验版 `gmall-publisher` 则以日活、GMV 两个指标做最小闭环（[SugarController.java:26-87](gmall-publisher/src/main/java/com/atguigu/gmallpublisher/controller/SugarController.java)），适合先跑通链路再看完整版。

## 全链路全景

```mermaid
flowchart TB
    subgraph 数据源头
        DB[("MySQL 业务库<br/>binlog")]
        LOG["埋点 / 模拟行为日志"]
    end

    subgraph RT["gmall-realtime（Flink 1.13 计算）"]
        ODS["Kafka ODS<br/>topic_db · topic_log"]
        CFG["MySQL 配置表<br/>table_process（FlinkCDC 广播）"]
        DIM["app/dim → DimApp<br/>维表落地 Phoenix"]
        DWD["app/dwd → log / db 十五个明细主题<br/>写回 Kafka"]
        DWS["app/dws → 窗口聚合<br/>写 ClickHouse"]
        DIMJOIN["Redis 维表缓存<br/>关联明细与维表"]
    end

    subgraph 结果发布
        P1["gmall-publisher（实验版）"]
        P2["gmall-publisher-2022（完整版）"]
        UI["数据大屏可视化"]
    end

    DB -->|FlinkCDC 实时抓取| ODS
    LOG -->|上报 Kafka| ODS
    ODS --> DIM
    CFG -.驱动维度表动态过滤.-> DIM
    ODS --> DWD
    DWD --> DWS
    DWS -.查询维表.-> DIMJOIN
    DWS --> P1
    DWS --> P2
    P1 --> UI
    P2 --> UI
```

维表读取 Redis 缓存的证据在 `DimUtil`：按 `DIM:表名:id` 拼 Key、提供删除与查询入口（[DimUtil.java:27-49](gmall-realtime/src/main/java/com/atguigu/utils/DimUtil.java)），配合 `app/func` 里的 `DimJoinFunction`、`DimAsyncFunction` 在 DWS 作业中做维表关联。

## 建议阅读路线

这是一份导读，后续页面请沿着下表推进；每页只深挖一个主题，本页不再展开：

| 顺序 | 主题 | 仓库里的主入口 | 后续页要回答的问题 |
| --- | --- | --- | --- |
| 1 | 架构定位 | 本文 + 三个 `pom.xml` | 模块边界为什么这样切，技术选型如何呼应教学 |
| 2 | 数据流 | README 分层逻辑 [README.md:35-70](README.md)、`BaseLogApp` | 一条日志/一个订单如何从源头流到各层 |
| 3 | 计算存储 | `DimApp`、`app/dws/*`、`GmallConfig` | 每层“加工什么、存到哪、为何这么存” |
| 4 | 系统优化 | README 调优部分 [README.md:651-1035](README.md) | 并行度、Checkpoint、反压、数据倾斜、FlinkSQL 优化的实战注解 |
| 5 | 业务实现 | 15 个 DWD 主题与 `gmall-publisher-2022` | 交易/流量/工具/互动/用户各域的指标如何一步步算出并展示 |

## 收尾

一句话记住这个仓库：**`gmall-realtime` 用 Flink 把「业务库 binlog + 埋点日志」按 DIM/DWD/DWS 加工成「维度（Phoenix）→ 明细（Kafka）→ 汇总（ClickHouse）」三层结果，两个 publisher 再把 ClickHouse 的汇总查出来喂给大屏**。阅读时始终带着这条主线，就不会在 59 个类、十几个 Kafka 主题里迷路；后续页面各自展开其中一段，这里的分工即为其索引。技术栈与模块定位同时见 [README.md:9-31](README.md) 与根 [pom.xml:7-15](pom.xml)。
