2. Flink 基础回顾:架构、核心概念与开发环境搭建

在进入实时特征服务开发之前,有必要系统回顾 Flink 的核心基础。本章将围绕 Flink 的运行时架构、核心编程抽象(DataStream、算子、时间语义)以及开发环境搭建三个维度展开,为后续的因子计算实战打下坚实的技术根基。

2.1 Flink 运行时架构

Flink 采用经典的 主从(Master-Worker)架构,由 JobManager 和 TaskManager 两个核心组件构成,配合 Dispatcher 和 ResourceManager 实现作业的提交、调度与容错。

架构要点: JobManager 负责作业的协调与 Checkpoint 触发;TaskManager 负责执行具体的算子任务(Task),每个 TaskManager 内部包含多个 Task Slot,Slot 是资源调度的最小单位。
Flink 运行时架构 Flink Client Dispatcher JobManager 作业调度 · Checkpoint 协调 · 故障恢复 ResourceManager 资源分配 TaskManager 1 Slot 1 | Slot 2 | Slot 3 数据交换 · 算子执行 TaskManager 2 Slot 1 | Slot 2 | Slot 3 数据交换 · 算子执行

2.2 核心概念:DataStream、算子与时间语义

2.2.1 DataStream 与数据流模型

DataStream 是 Flink 流处理的核心抽象,代表一个持续不断、可能有界或无界的数据流。所有算子操作都围绕 DataStream 展开,包括转换(Transformation)、分区(Partitioning)、窗口(Window)和状态(State)管理。

概念 说明 典型场景
DataStream<T> 未分区的流,元素类型为 T 从 Kafka Source 读取原始事件
KeyedStream 按 Key 分区的流,支持状态与窗口 按用户 ID 分组计算累计特征
WindowedStream 在 KeyedStream 上定义窗口后的流 每 5 分钟统计一次滑动平均
ConnectedStreams 两条流的连接,可共享状态 实时特征与标签流的关联

2.2.2 常用算子分类

Flink 算子按功能可分为 基本转换算子、KeyBy 与分区算子、窗口算子 和 状态算子 四大类。以下列出特征服务开发中最常用的算子:

  • map / flatMap / filter:单元素转换、一对多展开、条件过滤。
  • keyBy:按指定 Key 对数据流进行逻辑分区,后续才能使用状态和窗口。
  • reduce / aggregate:增量聚合,适合滑动平均、累加器等特征。
  • process:最灵活的算子,可访问时间、状态和输出,适合复杂特征逻辑。
  • assignTimestampsAndWatermarks:分配时间戳并生成 Watermark,驱动事件时间窗口。
开发建议: 在实时特征服务中,keyBy + process 是最常用的组合。process 算子可以同时管理多个状态变量,并精确控制输出时机,非常适合因子计算中的多步聚合逻辑。

2.2.3 时间语义与 Watermark

Flink 支持三种时间语义,在特征服务中 事件时间(Event Time) 是最常用的选择,因为它能正确处理乱序数据和回填场景。

时间语义 定义 特征服务适用性
事件时间(Event Time) 事件实际发生的时间,由业务字段携带 ✅ 推荐,能处理乱序和延迟数据
摄入时间(Ingestion Time) 事件进入 Flink 的时间 ⚠️ 仅用于对时间精度要求不高的场景
处理时间(Processing Time) 算子所在机器的当前系统时间 ❌ 不推荐,结果不可复现

Watermark 是事件时间窗口的“进度信号”,表示“当前时间之前的数据已经全部到达”。Watermark 的生成策略直接影响窗口触发时机和特征计算的准确性。

事件时间窗口与 Watermark 推进 t0 t1 t2 t3 窗口 [0, 10s) 窗口 [10s, 20s) 窗口 [20s, 30s) Watermark = 当前最大事件时间 - 允许延迟 当 Watermark 越过窗口右边界时,该窗口立即触发计算并输出结果 迟到的数据将被丢弃或送入侧输出流(Side Output)

2.3 Flink 开发环境搭建

2.3.1 环境依赖清单

在开始编码之前,需要确保以下基础环境就绪:

  • JDK 8 或 11(推荐 JDK 11,Flink 1.14+ 官方支持)
  • Apache Maven 3.6+ 或 SBT 1.5+(Scala 项目)
  • IDE:IntelliJ IDEA(推荐)或 Eclipse
  • Git:用于版本管理和项目模板克隆

2.3.2 Maven 项目模板(推荐)

使用 Flink 官方提供的 Maven Archetype 快速生成项目骨架:

mvn archetype:generate \
  -DarchetypeGroupId=org.apache.flink \
  -DarchetypeArtifactId=flink-quickstart-java \
  -DarchetypeVersion=1.17.1 \
  -DgroupId=com.featurefactory \
  -DartifactId=realtime-feature-service \
  -Dversion=1.0.0 \
  -Dpackage=com.featurefactory \
  -DinteractiveMode=false

生成后的项目结构如下:

realtime-feature-service/
├── pom.xml
└── src/
    └── main/
        ├── java/com/featurefactory/
        │   ├── StreamingJob.java        # 主入口
        │   └── FeatureCalculator.java   # 特征计算逻辑
        └── resources/
            └── log4j.properties

2.3.3 SBT 项目模板(Scala 用户)

对于 Scala 项目,推荐使用 sbt-flink-template 或手动配置 build.sbt:

// build.sbt
name := "realtime-feature-service"
version := "1.0.0"
scalaVersion := "2.12.17"

libraryDependencies ++= Seq(
  "org.apache.flink" %% "flink-streaming-scala" % "1.17.1",
  "org.apache.flink" %% "flink-clients" % "1.17.1",
  "org.apache.flink" % "flink-connector-kafka" % "1.17.1"
)
版本兼容性注意: Flink 1.17 要求 Scala 2.12 或 2.13。如果使用 Scala 2.13,请将 scalaVersion 改为 2.13.10,并将依赖中的 %% 替换为 _2.13 显式指定。

2.3.4 本地运行验证

在 IDE 中直接运行 StreamingJob.main(),Flink 会自动启动一个嵌入式 MiniCluster,无需额外部署。验证输出日志包含以下内容即表示环境搭建成功:

INFO  org.apache.flink.runtime.minicluster.MiniCluster  - Starting Flink Mini Cluster
INFO  org.apache.flink.runtime.executiongraph.ExecutionGraph  - Job "Flink Streaming Job" switched to state RUNNING
INFO  com.featurefactory.StreamingJob  - Feature calculation pipeline started.

2.4 本章小结