1. 课程导学与前置准备:Flink与Delta Lake概述

大家好,欢迎来到《Flink与Delta Lake实时分析实战》的第一章。

在正式开始敲代码之前,我想先聊聊这门课到底要解决什么问题。说白了,就是帮你打通「实时计算」和「可靠存储」之间的那堵墙。我见过太多团队,Flink 跑得飞起,结果数据一落地就乱成一锅粥;也见过有人把 Delta Lake 当离线表用,白白浪费了它的流式能力。

这门课的目标很直接:让你能亲手搭一套端到端的实时数仓,从数据摄入到分析查询,每一步都稳得住。

1.1 为什么是 Flink + Delta Lake?

先说说 Flink。做实时计算的人,几乎绕不开它。Flink 的优势在于「真正的流处理」,而不是把流切成微批。我在项目中遇到过好几次,用 Spark Streaming 处理乱序数据,延迟和准确性总是顾此失彼。换成 Flink 之后,事件时间、水位线、精确一次语义,这些机制帮了大忙。

再说 Delta Lake。它本质上是一个给数据湖加事务支持的存储层。ACID 事务、Schema 演进、时间旅行,这些特性让数据湖不再是个「垃圾场」。你想想看,如果没有 Delta Lake,Flink 往 HDFS 写数据时,一旦任务失败,留下的半成品文件能把下游分析搞崩溃。

两者结合,Flink 负责「快」,Delta Lake 负责「稳」。一个典型的场景是:Flink 消费 Kafka 中的用户点击流,实时清洗、聚合,然后以 Delta Lake 格式写入 OSS 或 HDFS。下游的 Ad-hoc 查询或者 BI 报表,直接读 Delta 表就能拿到一致的数据。

核心价值一句话总结:Flink 保证数据算得对、算得快;Delta Lake 保证数据存得稳、查得准。

1.2 课程整体知识体系

这门课一共 30 章,我把它分成了四个阶段。下面这张图能帮你快速建立全局视角。

课程知识体系结构图 课程知识体系结构图 阶段一:基础与环境 第1-4章 概念、搭建、数据源 阶段二:核心开发 第5-15章 Flink SQL、DataStream 阶段三:集成实战 第16-25章 Flink + Delta 深度集成 阶段四:运维与调优 第26-30章 监控、调优、生产化 每个阶段都配有可运行的代码示例和数据集 建议按顺序学习,但阶段二和阶段三可以交叉参考 核心组件:Flink 1.17 + Delta 2.4 数据源:Kafka + 模拟日志生成器 存储:本地文件系统 / OSS / HDFS

1.3 环境搭建:工欲善其事,必先利其器

这部分我尽量精简,但该装的依赖一个都不能少。我个人习惯用 Mac 或 Linux 做开发,Windows 用户建议装个 WSL2,能省掉很多路径和权限的麻烦。

1.3.1 JDK 与 Maven

Flink 1.17 要求 JDK 11,Delta Lake 2.4 也推荐 JDK 11。我建议直接用 JDK 11,别用 8 或 17 去冒险。

组件推荐版本备注
JDK11 (LTS)OpenJDK 或 Oracle JDK 均可
Maven3.8+用于项目构建和依赖管理
IDEIntelliJ IDEA 2023+社区版足够,建议安装 Scala 插件

验证安装的命令很简单:

java -version
# 输出应包含 "11.0.x"
mvn -version
# 输出应包含 "Apache Maven 3.8.x"

我曾经踩过的坑:JDK 版本不匹配。有一次我在生产环境用了 JDK 8 编译的 Flink 作业,部署到 JDK 11 的集群上,结果序列化报错。嗯,从那以后我统一了开发和生产环境的 JDK 版本。

1.3.2 IDE 配置建议

IntelliJ IDEA 是我最推荐的 IDE。装好之后,记得做两件事:

  • 安装 Scala 插件(如果要用 DataStream API 写 Scala)
  • 设置 Maven 自动导入,避免每次改 pom.xml 都手动刷新

另外,我习惯把项目的编码统一设为 UTF-8,不然中文注释在 Windows 上容易乱码。

1.4 数据源准备:让数据流动起来

没有数据,学实时计算就是纸上谈兵。这门课主要用两种数据源:

1.4.1 Kafka 作为流式数据管道

Kafka 是 Flink 最常用的数据源之一。我们会搭建一个单节点的 Kafka 集群,然后往里面灌模拟的点击流数据。每条消息包含用户 ID、页面 URL、事件时间戳和行为类型。

启动 Kafka 的步骤大致如下:

  1. 下载 Kafka 3.5+ 并解压
  2. 启动 Zookeeper(Kafka 内置了脚本)
  3. 启动 Kafka Server
  4. 创建一个 topic,比如 click_stream
# 启动 Zookeeper
bin/zookeeper-server-start.sh config/zookeeper.properties

# 启动 Kafka
bin/kafka-server-start.sh config/server.properties

# 创建 topic
bin/kafka-topics.sh --create --topic click_stream --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1

小提示:如果你本地资源有限,可以用 Docker Compose 一键拉起 Kafka + Zookeeper。我课程配套的代码仓库里已经准备好了 docker-compose.yml 文件。

1.4.2 模拟数据生成器

光有 Kafka 还不够,得有数据往里写。我写了一个简单的 Java 数据生成器,它会每隔 1 秒发送一条 JSON 格式的点击事件。你直接运行 main 方法就能看到数据在 Kafka 里流动。

// 模拟数据格式示例
{
  "userId": "u_1001",
  "pageUrl": "/product/12345",
  "eventTime": "2024-01-15T10:30:00Z",
  "action": "click"
}

这个生成器会随机生成 1000 个用户的行为,覆盖浏览、点击、加购、下单四种动作。数据量不大,但足够用来演示窗口聚合、去重和实时报表。

1.5 项目骨架与依赖管理

我们用一个 Maven 项目来组织代码。核心依赖就三个:Flink、Delta Lake 和 Kafka Connector。

<properties>
    <flink.version>1.17.0</flink.version>
    <delta.version>2.4.0</delta.version>
    <scala.binary.version>2.12</scala.binary.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-java</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-connector-kafka</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>io.delta</groupId>
        <artifactId>delta-standalone_${scala.binary.version}</artifactId>
        <version>${delta.version}</version>
    </dependency>
</dependencies>

这里要注意 Delta Lake 的 artifactId。早期版本叫 delta-core,2.4 之后改成了 delta-standalone。我刚开始升级时没注意,结果编译一直报类找不到,折腾了半天才发现是包名变了。

1.6 验证环境:跑一个 Hello World

环境搭好之后,我们写一个最简单的 Flink 作业来验证:从 Kafka 读取数据,打印到控制台。

public class KafkaHelloWorld {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        KafkaSource<String> source = KafkaSource.<String>builder()
            .setBootstrapServers("localhost:9092")
            .setTopics("click_stream")
            .setGroupId("flink-hello")
            .setStartingOffsets(OffsetsInitializer.latest())
            .setValueOnlyDeserializer(new SimpleStringSchema())
            .build();

        DataStream<String> stream = env.fromSource(source, WatermarkStrategy.noWatermarks(), "Kafka Source");

        stream.print();

        env.execute("Kafka Hello World");
    }
}

运行这个作业,同时启动数据生成器。如果你在控制台看到源源不断输出的 JSON 字符串,恭喜你,环境搭建成功了。

到这里,第一章的核心内容就结束了。你有了 JDK、Maven、IDE,有了 Kafka 和模拟数据,还跑通了第一个 Flink 作业。接下来,我们会深入 Flink 的编程模型,开始真正的实时分析之旅。