1. 课程导学与环境搭建:Flink与Kafka实时ETL概述
各位同学,欢迎来到《Flink与Kafka整合实现实时ETL》的第一章。我是你们这门课的主讲,一个在实时数据领域摸爬滚打了七八年的老工程师。今天咱们不急着敲代码,先聊聊这门课到底要讲什么,以及怎么把开发环境搭好。
说实话,我见过太多人一上来就扎进代码里,结果写到一半发现环境不对,或者根本不清楚自己在解决什么问题。所以这一章,咱们把地基打牢。
1.1 什么是实时ETL?为什么需要它?
ETL,说白了就是三个步骤:抽取(Extract)、转换(Transform)、加载(Load)。传统的ETL通常是跑批任务,每天凌晨跑一次,把数据从业务库抽到数仓里。但到了实时场景,这套逻辑就不太够用了。
你想想看,现在用户下了单,你希望立刻看到订单数据进入大屏;用户点击了广告,你希望秒级反馈给推荐系统。批处理跑完可能要等几个小时,黄花菜都凉了。
实时ETL,就是让数据在流动的过程中完成清洗、过滤、聚合、关联,然后直接写入目标存储。整个过程是流式处理,数据一条一条地进来,一条一条地出去。
核心区别一句话:批处理是「攒够了再干」,实时ETL是「来一条干一条」。
我在项目中遇到过这样一个场景:某电商平台的大促活动,流量峰值是平时的50倍。如果还用批处理,数据延迟会直接导致运营决策滞后。后来我们改用Flink+Kafka做实时ETL,延迟从小时级降到了秒级。嗯,效果立竿见影。
1.2 课程目标:你能学到什么?
这门课一共30章,咱们的目标很明确——让你能独立搭建一套生产级的实时ETL管道。具体来说,学完之后你应该能做到:
- 理解Flink和Kafka的核心原理,不只是会用API
- 能设计并实现从Kafka消费数据、用Flink做转换、再写回Kafka或其他存储的完整流程
- 掌握状态管理、容错机制、水位线等进阶内容
- 能处理实际项目中的常见坑,比如数据倾斜、背压、序列化问题
我个人习惯把课程分成三个阶段:前10章打基础,中间10章深入核心机制,最后10章做实战项目。咱们现在就在第一阶段。
1.3 技术栈介绍:为什么选Flink和Kafka?
市面上实时计算框架不少,Storm、Spark Streaming、Flink……为什么我推荐Flink?
| 特性 | Flink | Spark Streaming | Storm |
|---|---|---|---|
| 处理模型 | 真正的流式(逐条处理) | 微批次(攒一批处理) | 流式(逐条处理) |
| 状态管理 | 内置强状态(ValueState、MapState等) | 依赖外部存储 | 弱状态支持 |
| 精确一次语义 | 原生支持 | 支持(但开销大) | 至少一次 |
| 事件时间处理 | 成熟的水位线机制 | 支持但延迟较高 | 不原生支持 |
| 社区活跃度 | 极高(阿里、字节等大厂都在用) | 高 | 较低 |
至于Kafka,它已经是事实上的消息队列标准了。高吞吐、持久化、分区机制,天然适合做实时数据管道的数据源和结果输出。我见过不少团队尝试用RabbitMQ或Pulsar替代,但Kafka在生态整合上确实更成熟,尤其是和Flink的配合,几乎是无缝的。
我的建议:如果你刚接触实时ETL,Flink+Kafka是最不容易走弯路的技术组合。社区资料多,遇到问题基本都能搜到答案。
1.4 知识体系总览
下面这张图,是我自己梳理的课程知识体系。你可以把它当成一张地图,学完一章就回来看看,心里有个数。
1.5 开发环境准备
好了,理论聊完了,咱们开始动手。环境搭建这块,我踩过不少坑,下面直接给你一份「避坑版」的步骤。
1.5.1 JDK 安装与配置
Flink 1.13 以上版本要求 JDK 8 或 11。我个人推荐 JDK 11,性能和内存管理更好一些。
# 下载 JDK 11(以 Linux 为例)
wget https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz
# 解压
tar -zxvf openjdk-11.0.2_linux-x64_bin.tar.gz -C /usr/local/
# 配置环境变量
export JAVA_HOME=/usr/local/jdk-11.0.2
export PATH=$JAVA_HOME/bin:$PATH
# 验证
java -version
# 输出应为:openjdk version "11.0.2" 2019-01-15
注意:千万不要用系统自带的 OpenJDK,版本太老容易出兼容性问题。我曾经在一个项目里因为JDK版本不对,Flink的Checkpoint一直失败,排查了两天才发现是JDK的bug。从那以后,我都是手动安装指定版本。
1.5.2 Maven 安装与配置
Maven 3.6.0 以上版本都可以。我习惯用 3.8.1,稳定。
# 下载 Maven
wget https://archive.apache.org/dist/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz
# 解压
tar -zxvf apache-maven-3.8.1-bin.tar.gz -C /usr/local/
# 配置环境变量
export MAVEN_HOME=/usr/local/apache-maven-3.8.1
export PATH=$MAVEN_HOME/bin:$PATH
# 验证
mvn -version
记得配置阿里云镜像,不然下载依赖能等到你怀疑人生:
<!-- ~/.m2/settings.xml -->
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
</mirrors>
1.5.3 IDE 选择与配置
IntelliJ IDEA 是首选,社区版就够用。如果你用 Eclipse,也不是不行,但Flink的调试体验会差一些。
我建议安装这几个插件:
- Lombok:减少样板代码
- Rainbow Brackets:括号多的时候一眼就能看清层级
- GitToolBox:方便看代码提交记录
1.5.4 创建第一个Flink + Kafka项目
咱们用 Maven 快速创建一个项目骨架:
mvn archetype:generate \
-DarchetypeGroupId=org.apache.flink \
-DarchetypeArtifactId=flink-quickstart-java \
-DarchetypeVersion=1.14.0 \
-DgroupId=com.example \
-DartifactId=flink-kafka-etl \
-Dversion=1.0-SNAPSHOT \
-Dpackage=com.example.etl \
-DinteractiveMode=false
生成之后,在 pom.xml 里加上 Kafka 连接器的依赖:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka_2.12</artifactId>
<version>1.14.0</version>
</dependency>
小技巧:Flink 和 Kafka 的版本要匹配。比如 Flink 1.14 对应 Kafka 2.8.x 比较稳。版本不对的话,序列化会报一些奇奇怪怪的错误。我吃过这个亏,后来每次升级都会先查一下兼容性矩阵。
1.6 环境验证:跑一个简单的测试
环境搭好了,咱们写个最简单的程序验证一下:从Kafka读取数据,打印到控制台。
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import java.util.Properties;
public class KafkaFlinkTest {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
Properties props = new Properties();
props.setProperty("bootstrap.servers", "localhost:9092");
props.setProperty("group.id", "test-group");
FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>(
"input-topic",
new SimpleStringSchema(),
props
);
env.addSource(consumer)
.map(value -> "收到消息: " + value)
.print();
env.execute("Kafka Flink Test");
}
}
启动之前,确保你的Kafka已经运行,并且创建了 input-topic。如果控制台能打印出消息,说明环境没问题。