# 大数据与数仓实验实训教学案例库 · 总体实验实训文档

> 适用课程：大数据技术原理与应用 / 数据仓库与数据挖掘 / 数据工程实训
> 配套材料：`教学/` 目录 8 个实验 Notebook、`PPT/` 目录 8 份实验课件、`高频面试题详解.md`
> 运行约束：全部实验在**单机 + 纯 Python**（numpy / pandas / matplotlib / sqlite3）环境完成，不依赖任何集群。

---

## 1. 课程定位与教学目标

本案例库面向大数据方向的高年级本科生与研究生，以"**用模拟实现讲透机制**"为教学方法：不搭建 Hadoop/Spark/Flink 集群，而是用几百行 Python 代码把分布式系统的核心机制（分块副本、Shuffle、惰性求值、窗口水位线、数仓分层、消息分区、DAG 调度）逐一手写出来。学生做完 8 个实验，能同时达到两个目标：

1. **理解原理**——知道每个系统"为什么这样设计"，能画图、能推导、能解释取舍；
2. **通过面试**——覆盖大数据开发、数仓、实时计算、数据平台岗位的高频考点，配套 86 道面试题详解。

**教学目标（认知层级对应）**

| 层级 | 目标 | 对应实验 | 检验方式 |
|---|---|---|---|
| 记忆 | 说出技术栈六层、四层数仓、组件分工 | 00、04 | 速答题 |
| 理解 | 解释分块/副本/Shuffle/Watermark/分区的动机与代价 | 00–05 | 概念题 + 画图 |
| 应用 | 手写词频统计、窗口、拓扑排序、TopN、两阶段聚合 | 01–07 | 上机编程 |
| 分析 | 对给定场景选型（批/流、星型/雪花、分区数、副本策略）并说明理由 | 02–06 | 案例分析 |
| 评价 | 诊断数据倾斜、消息积压、指标对不上等问题并给出处理路径 | 05–07 | 情景问答 |

## 2. 面向对象与学情分析

- **先修要求**：Python 基础（函数、字典、列表）、SQL 基础（SELECT/GROUP BY/JOIN）、了解 Linux 命令行更佳但非必需。
- **典型困难**：初学者没有集群可摸，对"分布式"没有直观感受——本案例库用"一台电脑上的多列表/多进程模拟多节点"化解；对"为什么"类问题（为什么块要大、为什么 Shuffle 慢、为什么需要 Watermark）缺乏推导习惯——每个实验都安排"设计动机"讲解与反例验证。
- **与就业的关系**：知识点组织顺序即面试考察顺序（体系→离线→Spark→实时→数仓→管道→平台→冲刺），每个实验末尾的"自测清单"就是面试考点清单。

## 3. 实验环境与工具

| 项目 | 要求 | 说明 |
|---|---|---|
| 操作系统 | Windows / macOS / Linux 均可 | 教学环境以 Windows + Anaconda 为例 |
| Python | ≥ 3.9 | 建议 3.10+ |
| 依赖库 | numpy、pandas、matplotlib、sqlite3（标准库）、jupyter | `pip install numpy pandas matplotlib jupyter` |
| 硬件 | 普通笔记本（8GB 内存即可） | 全部实验无集群、无 Docker、可离线运行 |
| 字体 | matplotlib 中文字体 | 教学代码已统一设置 `Microsoft YaHei / SimHei` 等候选字体 |

每个 Notebook 均已通过 nbclient 执行验证：所有断言（assert）通过、与 pandas/SQL 的交叉验证一致、图形正常输出。学生可直接运行复现，也可以"先删输出再自己跑"作为练习。

## 4. 教学内容总览与课时安排

> 教学配图未随材料包提供（大数据技术栈六层全景）；相关机制图请查看对应 Notebook 与 PPT。

**八个实验的知识地图**（每个实验对应一套 PPT 与一份实训方案）：

| 实验 | 主题 | 核心动手内容 | 建议课时 |
|---|---|---|---|
| 00 | 大数据体系与 HDFS | 分块计算、3 副本容错模拟、读写流程 | 2 |
| 01 | MapReduce | 手写词频 Map→Shuffle→Reduce、TopN/均值变体 | 2 |
| 02 | Spark 核心与 RDD | 迷你 RDD、惰性求值证明、宽窄依赖、预聚合 | 2 |
| 03 | Flink 与实时计算 | 事件时间、滚动/滑动窗口手写、Watermark 推进 | 3 |
| 04 | Hive 与数仓建模 | sqlite3 四层分层 ETL、拉链表、星型/雪花 | 3 |
| 05 | Kafka 与数据管道 | 确定性哈希分区、消费者组与 offset、ACK 三档 | 2 |
| 06 | 数据平台与调度 | 拓扑排序、失败重试与依赖阻断、表级血缘 | 2 |
| 07 | 面试冲刺 | 30 秒全链路、TopN 分治、两阶段聚合抗倾斜 | 2 |

**建议教学顺序**：严格按编号推进。00–02 是"离线主线"（存储→批处理→内存计算），03 是"流式主线"，04–06 是"工程主线"（建模→管道→调度），07 收束串联。总课时 18 学时（含上机）。

## 5. 核心知识点详解

### 5.1 大数据体系与 HDFS（实验 00）

**为什么需要分布式**。单机的磁盘容量、读写吞吐、内存、可靠性都有上限；数据量到 TB/PB 级后，唯一出路是"分而治之 + 冗余容错"：把数据切开存到多机（分块），把每份再存多处（副本），把计算搬到数据附近（本地性）。Hadoop 三件套对应这三件事：HDFS（存储）、YARN（资源调度）、MapReduce（计算框架）。

**分块（Block）**。文件被切成固定大小的块存储，Hadoop 2.x 起默认块大小 128MB（参数 `dfs.blocksize`）。分块数按向上取整计算：

$$n = \left\lceil \frac{S}{B} \right\rceil,\quad \text{末块大小} = S-(n-1)B$$

块为什么这么大？设一次磁盘寻址约 10ms、磁盘顺序传输率约 100MB/s。块越大，"一次寻址"对应的有效传输越久，寻址开销占比越低；当块约 100MB 时寻址占比降到约 1%，继续增大收益递减，故取 128MB。**块是存储与容错的单位，而不是 I/O 的最小单位**（读取仍按字节流）。

**副本（Replication）**。默认 3 副本，机架感知放置策略：第 1 副本在客户端所在节点（集群外则随机）；第 2 副本放**另一个机架**；第 3 副本与第 2 副本**同机架不同节点**。这样任一节点故障有同机架副本兜底，任一机架故障仍有 1 个副本存活，同时同机架的第 3 副本节省跨交换机带宽。Hadoop 3.x 另提供**纠删码（Erasure Coding）**作为 3 副本的替代：RS(6,3) 编码存储开销约 1.5 倍（3 副本为 3 倍），但读路径与修复代价更高，适合冷数据。

> 教学配图未随材料包提供（HDFS 分块与 3 副本放置）；相关机制图请查看对应 Notebook 与 PPT。

**读写流程**。写：客户端向 NameNode 申请 → 按块流式写入第一个 DataNode，该节点以**流水线（pipeline）**方式把数据转发给副本节点 → 全部确认后提交 NameNode。读：客户端向 NameNode 拿"块 → DataNode 列表"的元数据 → **就近**从 DataNode 并行拉块拼装。核心设计：**NameNode 只管元数据，数据流不过 NameNode**，否则元数据节点立刻成为带宽瓶颈。NameNode 元数据常驻内存并靠 fsimage + editlog 持久化，块位置信息由 DataNode 心跳汇报；单点问题用 HA（Active/Standby + JournalNode + ZKFC 自动切换）解决。

> 教学配图未随材料包提供（HDFS 读写流程）；相关机制图请查看对应 Notebook 与 PPT。

**典型问题链**（面试高频）：块大 → 元数据少；文件小而多 → 每文件每块都是一条元数据 → NameNode 内存被海量小文件压垮（**小文件问题**）→ 治理手段：合并（SequenceFile/HAR）、按分区归档、改用湖格式（Iceberg/Hudi/Delta）。HDFS 只适合**大文件、高吞吐、一次写多次读**的场景，不支持低延迟随机点查（那是 HBase/Redis 的职责）。

### 5.2 MapReduce（实验 01）

**模型**。用户只实现两个函数：`map(k1,v1) → list(k2,v2)` 与 `reduce(k2, list(v2)) → list(v2)`。框架负责把中间结果按 `k2` 分组传输（Shuffle）。词频统计：map 输出 `(词, 1)`；reduce 对同一词求和。

**三阶段与并行度**。输入切成 M 个分片（split，默认一片 ≈ 一个 HDFS 块），M 个 Map 任务**数据本地**执行；Reduce 任务数 R 由用户指定，默认分区器 `hash(key) % R` 决定每条中间结果的去向——相同 key 必然落入同一 Reduce，这是"跨机器分组"能够成立的关键。

> 教学配图未随材料包提供（MapReduce 全流程）；相关机制图请查看对应 Notebook 与 PPT。

**Shuffle 为什么慢**。三个代价叠加：① Map 输出先写**环形缓冲区**（默认 100MB），到 80% 阈值就**溢写**磁盘，多个溢写文件再归并；② 排序：为了按键分组，每个溢写文件内部排序、归并时再排序；③ 网络传输：Reduce 端通过 HTTP 从每个 Map 节点拉取属于自己的分区。**Combiner**（可选的 map 端局部聚合）是第一优化：对求和/最值这类满足结合律的运算，能成倍减少传输量；**求平均不能直接 Combiner**——先局部平均再平均 ≠ 总平均，正确做法是传 (和, 计数) 二元组（实验 01 有对照验证）。

**局限与被替代的原因**。中间结果必须落盘、每次作业冷启动（JVM、读盘）、没有 DAG 表达力、迭代计算要把数据反复搬进搬出——这正是 Spark（内存 + DAG 流水线）替代它的原因。今天 MR 更多以"Hive on MR 的历史包袱"形式存在，新集群普遍用 Tez/Spark 作为执行引擎。

### 5.3 Spark 核心与 RDD（实验 02）

**RDD 三要素**：①一组分区；②作用于分区的一组转换（依赖列表即**血缘 Lineage**）；③可选的缓存位置。RDD 不可变，转换产生新 RDD。"弹性"体现在：分区可并行、故障可沿血缘重算、数据可在内存/磁盘间自动取舍。

**惰性求值**。`map/filter/groupBy` 等 Transformation 只"记动作不执行"，直到 `collect/count/reduce/take` 等 **Action** 出现才生成作业。好处：①框架看到完整 DAG 后能做全局优化（合并窄依赖、裁剪无用分支）；②避免为中间结果白白付网络/磁盘成本。

> 教学配图未随材料包提供（Spark 惰性求值与 Stage 划分）；相关机制图请查看对应 Notebook 与 PPT。

**宽窄依赖**。窄依赖：每个父分区最多被一个子分区消费（map、filter、union）——同 Stage 内**流水线**执行，无 Shuffle；宽依赖：父分区被多个子分区消费（reduceByKey、join、groupByKey）——必须 Shuffle，且 Shuffle 边界就是 Stage 边界。**reduceByKey 优于 groupByKey**：前者在每个分区内部先做 map 端预聚合（combine），跨网络传输的是"局部和"；后者把原值全部传过去。

> 教学配图未随材料包提供（宽窄依赖）；相关机制图请查看对应 Notebook 与 PPT。

**执行流程**。`spark-submit` → Driver 构建 DAG → Action 触发 Job → DAGScheduler 按宽依赖切 Stage → 每 Stage 按"1 分区 = 1 Task"生成 TaskSet → TaskScheduler 派发到 Executor 执行 → 结果回传 Driver。**分区数经验**：不低于总核心数，常见取总核心数的 2–3 倍（忙核可接长尾任务）；SQL Shuffle 分区由 `spark.sql.shuffle.partitions`（默认 200）控制。

**容错三层**：血缘重算（自动）、cache（把常用 RDD 放内存，lazy 生效，血缘仍在）、checkpoint（把 RDD 写入可靠存储并**切断血缘**，适合迭代算法的长血缘）。

**DataFrame 为什么取代 RDD**。RDD 的函数是黑盒（Catalyst 无法优化），DataFrame 带 schema，Catalyst 能做谓词下推、列裁剪、join 重排，Tungsten 做堆外二进制内存管理——生产代码以 Spark SQL 为主，RDD 只在需要精细控制分区时使用。

### 5.4 Flink 与实时计算（实验 03）

**批与流**。批处理：数据有界、跑完即止、延迟高但准确；流处理：数据无界、持续计算、低延迟但必须处理乱序。Lambda 架构（批流两套代码再合并）维护成本高、对账困难；Kappa 架构（一切皆流，需要历史时重放消息）在 Flink 成熟后成为主流。

**三种时间**。事件时间（数据自带的发生时刻）是正确性的基础；处理时间（算子机器时钟）用于低延迟近似场景；摄入时间少用。乱序是并行的必然结果，"按到达顺序统计"必然算错窗口。

**窗口三型**。滚动窗口（固定长、不重叠）：每条数据只属一个窗口，适合固定周期报表；滑动窗口（长 > 步长，重叠）：数据可属多个窗口，适合"最近 1 小时每 5 分钟"类监控；会话窗口（按活动间隙 gap 动态切分）：无固定长度，适合用户行为会话。

> 教学配图未随材料包提供（窗口对比）；相关机制图请查看对应 Notebook 与 PPT。

**Watermark（水位线）**。一个随数据流动的单调递增时间戳，定义

$$wm = \max(\text{已见事件时间}) - \text{允许乱序容忍}\ d$$

其含义是"事件时间 ≤ wm 的数据大概率都到齐了"。窗口关闭条件：wm 越过窗口终点。d 越大窗口关得越晚（越准但延迟越高），d=0 表示信任顺序到达（几乎必错）。多并行度下算子取各上游 watermark 的**最小值**（最保守）。

> 教学配图未随材料包提供（Watermark 推进与迟到数据）；相关机制图请查看对应 Notebook 与 PPT。

**迟到数据三策略**：① `allowedLateness`：窗口关闭后保留状态再等一段时间，迟到数据更新窗口结果；② 侧输出流（side output）：把太迟的数据导出到独立流，离线补偿；③ 丢弃（默认）。记忆口径：**Watermark 决定窗口何时关，allowedLateness 决定关了还能不能补**。

**状态与 Checkpoint**。流计算要"记住"中间结果（窗口累加、去重集合），这就是状态，存于状态后端（堆内存 / RocksDB）。Checkpoint 采用 **Chandy-Lamport 异步屏障快照**：屏障随数据流动，算子收齐输入屏障后快照状态到远程存储，几乎不阻塞计算；故障时全图从最近快照恢复并重放输入。**精确一次（Exactly-once）** = Checkpoint 恢复 + Sink 两阶段提交（预提交→快照完成→正式提交）。

**Flink vs Spark Streaming**。真流（逐条、毫秒级）vs 微批（攒批、秒级）；Flink 原生状态与事件时间语义更完善。Flink 2.0（2025-03 发布）进一步引入分离式状态存储与物化表，批流一体能力继续加强。

### 5.5 Hive 与数仓建模（实验 04）

**数据库 vs 数仓**。OLTP 数据库为高频事务而生（读写几行、三范式防冗余）；数仓为分析而生（扫描亿级行、用冗余换查询速度）。分析直连生产库会拖垮线上业务，因此数据 T+1 同步进入数仓再分层加工。

**四层模型**（必背）：

| 层 | 全称 | 职责 | 粒度 | 典型表 |
|---|---|---|---|---|
| ODS | Operational Data Store | 贴源存储，原样保留（含脏数据） | 与源一致 | ods_orders |
| DWD | Data Warehouse Detail | 清洗、标准化、维度退化 | 最细事实粒度 | dwd_orders |
| DWS | Data Warehouse Summary | 按主题轻度汇总（日/城市等维度组合） | 粗一档 | dws_daily_orders |
| ADS | Application Data Service | 面向报表/大屏/算法特征 | 结果级 | ads_gmv_top3 |

分层的价值：**解耦**（上游口径变化只影响下一层）、**复用**（DWS 一次加工多处使用）、**质量**（逐层校验，问题在 DWD 就暴露）、**成本**（中间结果只算一次）。实验 04 用 sqlite3 把 ODS→DWD→DWS→ADS 完整走了一遍，包括：city 缺失补"未知"、refunded 转有效标志 is_valid、抽 dt 分区字段、按 (dt, city) 汇总、Top 城市。

> 教学配图未随材料包提供（数仓四层）；相关机制图请查看对应 Notebook 与 PPT。

**教学重点：去重计数的陷阱**。DWS 按 (dt, city) 做了 `COUNT(DISTINCT user_id)`，ADS 层把各行 SUM 起来会**重复计数**（同一用户两天/两城市被算多次）。跨组去重必须回到明细层单独统计。这是初学者最常踩的口径错误。

**维度建模三型**。事实表 = 可加数值的业务过程（订单金额），维度表 = 描述上下文的实体（用户/商品/时间）。星型模型：维度直连事实，join 少查询快（BI 报表首选）；雪花模型：维度再规范化拆分，省空间但 join 多；宽表（维度退化）：常用维度直接冗余进事实表，DWS/ADS 最常用、最快。

> 教学配图未随材料包提供（星型 vs 雪花）；相关机制图请查看对应 Notebook 与 PPT。

**缓慢变化维与拉链表**。维度属性随时间变化（用户搬家）。Type 1 直接覆盖（丢历史）；Type 2 版本化：旧记录封版（end_date=变更日前一天），新记录开链（end_date=9999-12-31 表示当前有效）。拉链表是 Type 2 的标准落地，每天两条 SQL（闭链 + 开链）完成更新，支持"任意时间点回看"。实验 04 有完整 sqlite3 实现。

**Hive 定位**。Hive 是 SQL 引擎而非数据库：schema 存 Metastore，数据是 HDFS 上的普通文件，查询被翻译成 MR/Tez/Spark 任务；分区是目录级裁剪（`dt=2024-05-01/`），分桶是文件级哈希切分。

### 5.6 Kafka 与数据管道（实验 05）

**定位**。Kafka 是分布式提交日志/消息队列，在链路中承担**解耦**（上游不感知下游数量与故障）、**削峰**（突发流量先进队列缓释）、**缓冲**（下游按自己的节奏消费）、**回放**（消息按保留期落盘，可重新消费）。

**核心概念**。Topic（逻辑类别）→ Partition（物理分片，**分区内严格有序**，offset 从 0 递增）→ Broker（服务节点，存分区副本，1 Leader + N Follower）。生产者按 key 路由：`hash(key) % 分区数`——同一 key（同一用户/订单）的消息进入同一分区，从而获得分区内有序性；要**全局有序只能单分区**（牺牲并行度）。

> 教学配图未随材料包提供（Kafka 架构）；相关机制图请查看对应 Notebook 与 PPT。

**消费者组**。组内消费者**互斥**地分摊分区（一个分区同一时刻只属于组内一个消费者；消费者数 > 分区数时多出的消费者闲置）；组间**广播**（每个组都收到全量消息）。消费者**提交 offset** 记录消费进度；消费者增减触发 **Rebalance**，期间整组暂停消费、恢复后可能重复消费——需要消费端幂等。Kafka 4.0（2025-03）的 KIP-848 新消费者组协议改为 Broker 协调的增量重平衡，明显缩短暂停时间。

**offset 进度与积压**。"最新 offset − 已提交 offset = 积压量"。积压处理路径：先定位（下游慢在处理还是拉取）→ 消费端提速（批量拉取、异步处理、优化反序列化）→ 并行扩容（加分区 + 加消费者，注意 key 路由变化）→ 极端情况临时降级（跳过非关键消息，事后补数）。

> 教学配图未随材料包提供（消费进度与 Rebalance）；相关机制图请查看对应 Notebook 与 PPT。

**可靠性三件套**。生产端 acks：0（不等待，可能丢）、1（Leader 落盘即确认，Leader 挂且未同步时可能丢）、all/−1（ISR 全部确认才返回，最稳；配合 `min.insync.replicas≥2` 与 3 副本使用）。消费端三语义：at-most-once（先提交后处理，可能丢）、at-least-once（先处理后提交，可能重）、exactly-once（幂等写/事务）。**面试标准答案：3 副本 + acks=all + min.insync.replicas=2 + 消费端幂等去重**。

**为什么高吞吐**：顺序写（追加日志）、零拷贝（sendfile，页缓存直达网卡）、批量压缩（linger.ms 攒批 + lz4/zstd）、依赖 OS 页缓存。

### 5.7 数据平台与调度（实验 06）

**数据平台三大块**：开发平台（SQL IDE、任务发布、版本管理）、调度系统（DAG 编排、定时、依赖、重跑）、治理体系（血缘、质量、元数据、权限）。

**任务依赖 = DAG**。任务用"依赖上游表"表达：ods_sync → dwd_clean → dws_agg → (ads_report, ads_feature)。**拓扑排序**给出可执行顺序（入度 0 的先进队，处理完减邻居入度）；若排序结果覆盖不了全部任务，说明存在环（非法依赖）。

> 教学配图未随材料包提供（调度 DAG 与失败重试）；相关机制图请查看对应 Notebook 与 PPT。

**失败处理策略**：指数退避重试（1min/5min/15min）→ 超限告警 → **依赖阻断**（上游失败时下游一律不跑，防止用残缺数据算出错误指标）→ 数据修复后补数（backfill，按天级分区批量重跑历史）。

**数据时间 vs 运行时间**：凌晨 1:30 运行的是昨天（T-1）的数据；"数据时间"写在分区里（ds=20261007）。排查数据问题三连问：任务跑了吗？跑到几点？处理的是哪天的分区？

**表级血缘**。记录"产出表 ← 消费表"关系，三大用途：①影响分析（改 ODS 表前先看下游有哪些报表/特征会变）；②故障溯源（报表异常沿血缘向上找源头）；③治理（无下游的孤儿表下线省成本）。

> 教学配图未随材料包提供（表级血缘）；相关机制图请查看对应 Notebook 与 PPT。

**调度工具选型**：Airflow（Python 代码定义 DAG，生态强，适合代码化团队）vs DolphinScheduler（可视化拖拽 + 多租户，对大数据栈友好）；新趋势还有 Dagster/Prefect（数据感知）与 Argo（K8s 原生）。

### 5.8 综合冲刺：全链路与两个手撕算法（实验 07）

**30 秒全链路串讲**（面试自我介绍的骨架）：

> 教学配图未随材料包提供（全链路）；相关机制图请查看对应 Notebook 与 PPT。

> 业务库/日志 → 采集（Kafka/Flume）→ 存储（HDFS/湖）→ 离线计算（Hive/Spark）→ 数仓四层（ODS→DWD→DWS→ADS）→ 报表/特征；实时支线：Kafka → Flink → 实时指标/风控；调度 + 血缘 + 质量 + 权限贯穿全程。

**手撕一：全局 TopN 分治**。每个分区只保留局部 TopN（数据量从 n 压到 N×分区数），再归并求全局 TopN。正确性依据：全局 TopK 一定包含在每个分区的局部 TopK 的并集中（反证：若某元素不在其分区局部 TopK 内，则该分区至少有 K 个元素比它大，全局就有 ≥K 个元素比它大，矛盾）。

**手撕二：两阶段聚合抗倾斜**。热点 key（如"hot"占 90% 记录）使单个 task 成为长尾。第一阶段给 key 加随机前缀（hot#0/hot#1/hot#2）打散到多个 task 并行聚合；第二阶段按原 key 合并。结果与单阶段一致，计算均匀。同思路在 SQL 里表现为"随机数打散 + 两轮 GROUP BY"，在 join 倾斜里表现为"热点 key 单独拎出广播 join"。

## 6. 实验实训实施流程（四步法）

每个实验按统一节奏组织（约 2–3 学时）：

| 步骤 | 内容 | 时间 | 检验 |
|---|---|---|---|
| ① 课前预习 | 通读实验 Notebook 的 markdown、观看对应 PPT、完成"本节要解决的问题"自问 | 课前 30min | 预习题 3 道 |
| ② 课堂精讲 | 教师用 PPT 讲原理与设计动机，黑板/图示走一遍数据流 | 30–45min | 随堂提问 |
| ③ 上机实操 | 学生逐 cell 运行 Notebook，完成标注为"动手验证"的改动（改参数、改副本数、改窗口大小）并解释结果变化 | 40–60min | 实验记录单 |
| ④ 课后检验 | 完成"自测清单"、对应章节面试题（配详解）、撰写实验报告 | 课后 | 报告 + 抽查答辩 |

**实验报告统一模板**：实验目的 → 原理简述（含至少 1 张手绘图）→ 关键代码与解释 → 运行结果与分析 → 遇到的问题与解决 → 自测清单完成情况。

## 7. 考核与评价方案

| 环节 | 占比 | 评价要点 |
|---|---|---|
| 实验过程（8 次记录单） | 30% | 按时完成、结果正确、有真实的问题记录 |
| 实验报告（抽 3 份详评） | 30% | 原理表述准确、图表规范、分析有自己的话（对照模板逐项打分） |
| 上机测验（60min） | 25% | 现场完成 1 道手撕题（TopN/窗口/拓扑排序/两阶段聚合四选一）+ 2 道速答题 |
| 综合答辩（5min/人） | 15% | 用"全链路串讲"自选切入点，回答 2 个追问 |

**上机测验评分细则（手撕题 10 分）**：思路正确 3 分；代码可运行 4 分；边界处理（空输入/单元素/倾斜键）2 分；复杂度或优化说明 1 分。

## 8. 岗位能力映射与学习建议

| 岗位方向 | 侧重实验 | 加分点 |
|---|---|---|
| 大数据开发 | 00–03、05 | 手写 MR 词频、Watermark 推导、acks 与消费语义组合 |
| 数仓/数据仓库工程师 | 04、06、07 | 四层建模实操、拉链表、口径治理、两阶段聚合 |
| 实时计算 | 03、05、07 | 窗口三型、迟到三策略、Exactly-once 实现 |
| 数据平台 | 06 | DAG 调度、血缘、补数与监控 |
| 数据分析/数据科学 | 04 | 能读懂四层结构并自取 DWS/ADS 数据 |

**学习建议**：①先跑通再深究——所有代码可运行，先得到正确结果，再逐行理解；②每个"为什么"至少追问两层（为什么块大→为什么 128MB→为什么不 1GB）；③把自测清单当面试题练，对着墙讲出来（讲 ≠ 想）；④有余力把 Notebook 的模拟实现改造成多进程版本，体会真正的并行。

## 附录 A：验收标准清单

- [ ] 能画出大数据技术栈六层全景图并串讲一条数据全链路
- [ ] 能手算文件分块数、解释 3 副本机架感知放置、画出读写流程
- [ ] 能手写 MapReduce 词频统计并与 pandas 对照
- [ ] 能解释 RDD 惰性求值、血缘、宽窄依赖，说出分区数设置经验
- [ ] 能手写滚动/滑动窗口，推导 Watermark 并说出迟到三策略
- [ ] 能用 sqlite3 完成 ODS→DWD→DWS→ADS 四层 ETL 并实现拉链表
- [ ] 能讲清 Kafka 分区/offset/消费者组/重平衡与可靠性组合
- [ ] 能实现拓扑排序、失败重试阻断、两阶段聚合与 TopN 分治
- [ ] 能对照《高频面试题详解.md》完成 86 题自测

## 附录 B：实验环境快速上手

```bash
# 安装依赖（建议虚拟环境）
pip install numpy pandas matplotlib jupyter

# 启动 Jupyter，打开 教学/ 目录
jupyter lab

# 重新执行某个实验（清空输出后整体运行）
# 菜单：Run → Run All Cells
```

> 注：教学 Notebook 全部基于 numpy/pandas/matplotlib/sqlite3，无需 Hadoop/Spark/Flink/Kafka 安装；绘图已统一中文字体；每个 Notebook 末尾附自测清单，可独立完成"预习—上机—自测"闭环。
