每天认识一个组件:Apache Flink

一、引言

Apache Flink 是面向有界与无界数据流的分布式、有状态计算框架。它以流处理为基础,通过事件时间、Watermark、分布式状态、Checkpoint 和输入重放等机制,支持实时分析、持续 ETL、规则检测、CDC 与实时数仓等场景。

yaml 复制代码
数据处理需求的演进

离线报表
   |
   v
MapReduce:吞吐优先、阶段式批处理
   |
   +----------------------------+
   |                            |
   v                            v
更低处理延迟                更复杂业务语义
   |                            |
   |                      乱序、状态、窗口
   |                      故障恢复、持续计算
   +-------------+--------------+
                 |
                 v
        有状态流处理系统
                 |
                 v
        Apache Flink

Apache Flink 定义为:在 无界和有界数据流上执行有状态计算 的框架与分布式处理引擎。

这里包含三个核心概念:

  • 无界流 :只有起点,没有预先确定的终点,例如 Kafka 中持续产生的订单事件。
  • 有界流 :具有明确的起点和终点,例如对象存储中的一批历史日志。
  • 有状态计算 :当前记录的处理结果依赖此前数据,例如累计金额、设备当前状态或用户最近行为。

Flink 的基础思想常被概括为:批处理是有界流处理,实时处理是无界流处理。但"流批统一"不等于流任务与批任务采用完全相同的物理执行方式。Flink 在统一的数据流模型和 API 之上处理有界与无界输入,同时根据输入是否有界选择不同的调度、Shuffle、Join、状态和故障恢复策略。

sql 复制代码
                   Apache Flink 统一数据流模型

       无界数据流                            有界数据流
   Kafka / CDC / 设备事件               文件 / 历史快照 / 批量导入
          |                                     |
          v                                     v
   STREAMING 执行模式                    BATCH 执行模式
   持续运行、流水线传输                   阶段调度、中间结果物化
   Checkpoint 恢复                       批式故障恢复
          |                                     |
          +------------------+------------------+
                             |
                             v
                 DataStream / Table API / SQL
                             |
                             v
                     Flink Runtime

STREAMING 模式也可以处理有界数据; BATCH 模式只能处理所有 Source 都有界的作业。两者应得到相同的最终业务结果,但中间输出、资源占用和恢复方式可能不同。

三、运行时架构

一个 Flink 集群主要由 JobManager 和 TaskManager 两类进程组成。提交作业的 Client 负责构建并提交数据流,但它不属于运行时本身,提交完成后可以断开。

lua 复制代码
                     +--------------------+
                     |       Client       |
                     | 构建并提交 JobGraph |
                     +----------+---------+
                                |
                                v
+----------------------------------------------------------------+
|                         JobManager                              |
|                                                                |
|  +----------------+  +----------------+  +-------------------+  |
|  |   Dispatcher   |  | ResourceManager|  |     JobMaster     |  |
|  | REST / Web UI  |  | Slot 与资源协调 |  | 单个作业调度与恢复 |  |
|  +----------------+  +----------------+  +-------------------+  |
+-------------------------------+--------------------------------+
                                |
                    调度 Task / 协调 Checkpoint
                                |
              +-----------------+-----------------+
              |                                   |
              v                                   v
+-----------------------------+     +-----------------------------+
|        TaskManager 1        |     |        TaskManager 2        |
|                             |     |                             |
|  Slot 0: Source -> Map      |<--->|  Slot 0: KeyBy -> Window   |
|  Slot 1: Sink               |     |  Slot 1: Aggregate -> Sink |
|                             |     |                             |
|  状态、网络缓冲、数据交换     |     |  状态、网络缓冲、数据交换     |
+-----------------------------+     +-----------------------------+

3.1.JobManager

JobManager 是集群的协调者,主要负责:

  • 接收和管理作业;
  • 调度 Task;
  • 协调 Checkpoint;
  • 处理 Task 失败并触发恢复;
  • 向资源管理平台申请或释放资源;
  • 维护作业执行状态。

从职责上看,JobManager 内部包含三个重要组件:

组件 主要职责
Dispatcher 接收作业,提供 REST 接口和 Web UI,为作业启动 JobMaster
ResourceManager 管理 Task Slot,并对接 Standalone、YARN 或 Kubernetes
JobMaster 管理某一个具体作业的调度、状态和故障恢复

3.2.TaskManager

askManager 是执行实际计算的 Worker 进程,负责运行 Task、保存本地状态、缓存数据并与其他 TaskManager 交换数据。每个 TaskManager 可以提供一个或多个 Task Slot ,Slot 是 Flink 调度资源的基本单位。

需要注意:

  • Slot 不等于 CPU Core;
  • Slot 目前主要用于划分和隔离 Managed Memory,不提供严格的 CPU 隔离;
  • 一个 Slot 不一定只运行一个算子;
  • Operator Chaining 和 Slot Sharing 可以让多个算子或 Subtask 共享 Slot。

四、Flink作业提交执行流程

DataStream 程序从用户编写的 API 调用到实际执行,需要经过多层图结构转换。

yaml 复制代码
DataStream API
      |
      v
Transformation DAG
      |
      | StreamGraphGenerator
      v
StreamGraph
      |
      | 算子链、物理边、Slot Sharing
      v
JobGraph
      |
      | 按并行度展开
      v
ExecutionGraph
      |
      v
Task / Subtask
      |
      v
TaskManager 执行

各层图的作用如下:

图结构 含义
Transformation DAG 用户 API 所声明的转换关系
StreamGraph DataStream 拓扑的中间表示
JobGraph 提交给 JobManager 的逻辑执行图
ExecutionGraph 按并行度展开、用于调度和跟踪运行状态的图
Task/Subtask 最终部署到 TaskManager 的执行实例

例如,一个并行度为 100 的 JobVertex ,可能在 ExecutionGraph 中展开为 100 个 ExecutionVertex 。相邻且满足条件的算子还可以被合并为 Operator Chain,从而减少线程切换、序列化和网络传输开销。

五、时间语义

实时处理中的"时间"并不只有一种。

  • Processing Time

Processing Time 使用算子所在机器的系统时间。它延迟低、实现简单,但结果会受到网络延迟、背压、机器负载和故障恢复影响。

  • Event Time

Event Time 来自事件自身携带的业务时间,例如订单创建时间。即使记录乱序到达,Flink 仍可按照事件实际发生时间把它放入对应窗口,因此更适合要求结果可重现的业务计算。

less 复制代码
事件实际发生顺序:

事件 A(10:01) -> 事件 B(10:02) -> 事件 C(10:03)

网络到达顺序:

事件 B(10:02) -> 事件 A(10:01) -> 事件 C(10:03)

Processing Time 窗口:
按 B、A、C 到达系统的时间处理

Event Time 窗口:
按 10:01、10:02、10:03 的业务时间处理

Watermark 是 Flink 对事件时间进度的声明。可以把 Watermark(t) 近似理解为:系统认为事件时间已经推进到 t,原则上不再期待时间戳小于或等于 t 的事件。

Watermark 会触发事件时间窗口和定时器,但它不是"旧数据绝不可能再来"的物理证明。Watermark 推进得慢,结果通常更完整,但窗口输出更晚;推进得快,延迟更低,但更多数据会被判定为迟到。

ini 复制代码
事件时间轴

10:00       10:01       10:02       10:03       10:04
  |-----------|-----------|-----------|-----------|
                          ^
                   Watermark = 10:02

时间戳 <= 10:02 后续到达的事件
可能被视为迟到事件

在多分区或多输入算子中,事件时间通常受最慢输入的 Watermark 约束。某个长时间没有数据的分区可能阻止整体 Watermark 前进,因此生产环境还需要关注空闲分区检测。

六、状态机制

无状态算子只根据当前输入产生结果,例如字段映射和简单过滤;有状态算子则需要记住此前发生的事情。

典型状态包括:

  • 用户累计交易金额;
  • 设备最近一次运行状态;
  • 窗口中尚未聚合完成的数据;
  • 去重所需的历史标识;
  • 规则引擎中已经匹配的事件序列。

Flink 原生支持 Keyed State、Operator State、窗口状态和定时器。其中 Keyed State 与 Keyed Stream 使用一致的分区方式,处理某个 Key 的 Subtask 通常可以在本地访问对应状态。

css 复制代码
输入事件
   |
   v
keyBy(userId)
   |
   +------------+-------------+
   |            |             |
   v            v             v
Subtask 0    Subtask 1     Subtask 2
user A/C     user B/F      user D/E
   |            |             |
本地状态 A/C   本地状态 B/F   本地状态 D/E

State Backend 决定运行中的状态以什么形式存放和访问,以及如何生成状态快照。

  • HashMapStateBackend :状态保存在 JVM Heap 中,访问速度快,但规模受内存限制。
  • EmbeddedRocksDBStateBackend :状态序列化后保存在本地 RocksDB,可使用本地磁盘并支持增量 Checkpoint。

State Backend 与 Checkpoint Storage 不能混为一谈:

yaml 复制代码
State Backend
    |
    | 决定运行状态如何维护、如何生成快照
    v
TaskManager 中的运行状态
    |
    | Checkpoint
    v
Checkpoint Storage
    |
    | 决定快照最终保存在哪里
    v
文件系统 / 对象存储 / 其他可靠存储

两者都保存状态,但用途不同。

维度 Checkpoint Savepoint
主要用途 非预期故障恢复 升级、迁移、扩缩容等计划内运维
触发方式 系统周期性触发 用户显式触发
生命周期 通常由 Flink 管理和清理 由用户管理和删除
优化目标 创建效率和恢复速度 可移植性和运维灵活性
保留方式 可按策略清理 通常长期保留

七、Checkpoint 容错

对于流式作业,Flink 通过分布式快照和输入重放实现一致恢复。Checkpoint 会记录 Source 的消费位置以及各个有状态算子的状态快照。

rust 复制代码
Source             Operator A          Operator B          Sink
  |                    |                   |                 |
  |---- data ---------->------------------->---------------->|
  |                    |                   |                 |
  |-- Barrier 42 ----->|-- Barrier 42 ---->|-- Barrier 42 ->|
  |                    |                   |                 |
  |               保存状态 A-42        保存状态 B-42          |
  |                    |                   |                 |
  +------------ Checkpoint 42 完成 --------------------------+

当任务失败时,Flink 的恢复过程可以概括为:

yaml 复制代码
任务失败
   |
   v
找到最近一次成功 Checkpoint
   |
   +---------------------------+
   |                           |
   v                           v
恢复算子状态              恢复 Source 位置
   |                           |
   +-------------+-------------+
                 |
                 v
       重新读取后续输入
                 |
                 v
       恢复一致的数据流计算

完整容错能力至少依赖以下条件:

  • Checkpoint 已显式启用;
  • Source 能保存位置并从指定位置重放;
  • Checkpoint Storage 在节点故障后仍然可访问;
  • 重启策略和集群高可用配置正确;
  • Sink 能处理恢复时可能重新执行的写入。

八、Exactly-once 的边界

Flink 的 Exactly-once 首先表示:在启用 Exactly-once Checkpoint 并成功恢复后,每条输入对 Flink 管理状态 的效果等价于只发生一次。记录在物理执行层面仍可能被重新读取和重新计算。

yaml 复制代码
端到端 Exactly-once

可重放 Source
      |
      | 保存读取位置
      v
Flink 状态与 Checkpoint
      |
      | 一致恢复
      v
支持事务或幂等写入的 Sink
      |
      v
目标系统中的 Exactly-once 效果

端到端 Exactly-once 需要整条链路共同配合:

环节 必要条件
Source 能记录读取位置,并在恢复时重放
Flink 启用并成功完成 Exactly-once Checkpoint
Storage Checkpoint 数据持久可靠
Sink 支持事务提交、两阶段提交、幂等写入或原子提交
外部系统 能正确配合事务、幂等键或提交协议

九、资源平台与部署模式

9.1.资源平台

平台 适用情况 主要特点
Standalone 本地验证、固定裸机、已有进程管理平台 简单直接,但需要自行补齐进程拉起与资源管理
Native Kubernetes 云原生、弹性资源、容器化环境 Flink 可动态申请 TaskManager,适合 Application Mode
YARN 已有 Hadoop 大数据平台 可复用队列、权限与资源管理体系
Kubernetes Operator 希望声明式管理 Flink 作业 简化部署、升级、Savepoint 和生命周期管理

9.2.部署模式

  • Application Mode

每个 Application 拥有独立集群,应用结束后集群退出。其资源隔离和故障隔离较好,推荐生产环境采用这种方式。

css 复制代码
Application A -> Flink Cluster A
Application B -> Flink Cluster B
Application C -> Flink Cluster C
  • Session Mode

预先启动一个长期运行的集群,再向其中提交多个作业。

lua 复制代码
                +------------------+
Job A --------->|                  |
Job B --------->| Session Cluster  |
Job C --------->|                  |
                +------------------+

Session Mode 启动成本低,适合开发测试、交互式 SQL 或大量短作业,但不同作业会共享 JobManager、TaskManager 和故障域,可能出现资源竞争及相互影响。

十、核心特性与优势

10.1.核心特性

  • 流批统一

Flink 可以使用统一的数据流模型处理实时无界流和历史有界数据,并允许 DataStream、Table API 和 SQL 在同一运行时上执行。

统一并不意味着简单地把所有批任务当成永不停止的流任务。BATCH 模式可使用阶段式调度、阻塞式 Shuffle、中间结果物化及批专用 Join 和聚合策略。

  • 事件时间与乱序处理

Event Time、Watermark、窗口和迟到数据处理共同解决乱序场景。该机制适用于交易、设备、物流和日志等事件发生时间与到达时间不一致的业务。

  • 大规模有状态计算

Keyed State、Operator State、定时器及多种 State Backend 使 Flink 能维护长期运行的业务上下文。配合稳定的 Operator UID 和 Savepoint,状态还可随扩缩容重新分配。

  • 一致性容错

Flink 使用分布式快照、Checkpoint Barrier、Source 位置和输入重放恢复状态。对齐 Checkpoint 用 Barrier 形成一致切面;非对齐 Checkpoint 可以将部分在途数据纳入快照,缓解严重背压下 Barrier 长时间无法推进的问题。

  • 多层 API
API 适合场景
SQL 实时聚合、窗口、Join、持续 ETL
Table API 使用关系模型编写流批查询
DataStream API 自定义业务处理、状态和数据流转换
ProcessFunction 精细控制状态、时间、定时器及侧输出
  • 连接器生态

Flink 提供 Kafka、文件系统、JDBC、Pulsar、Cassandra、Elasticsearch、OpenSearch、Kinesis 和 MongoDB 等连接器。许多连接器采用独立版本发布,且不一定包含在 Flink 二进制发行包中,选型时必须核对连接器与 Flink 主版本的兼容范围。

  • 业务时间语义完整

Flink 不只是快速处理记录,还能表达事件时间、乱序、迟到、窗口和定时器。对于依赖真实业务时间的指标,这比单纯按消息到达时间计算更可靠。

  • 状态是一等能力

在 Flink 中,状态不是开发者自行维护的外部缓存,而是可以参与 Checkpoint、恢复、扩缩容和重新分配的运行时资源。这降低了大规模状态计算的实现难度。

  • 一致性与性能可权衡

Watermark、允许迟到时间、Checkpoint 间隔、State Backend 和对齐策略都允许开发者在完整性、延迟、吞吐、存储和恢复时间之间做工程权衡。

  • API 与运行时统一

SQL、Table API 和 DataStream API 共享底层执行引擎,业务可以用 SQL 实现常规聚合,并在复杂规则处切换到 DataStream 或 ProcessFunction。

十一、适用场景

  • 实时指标与分析

例如分钟级成交额、在线人数、设备告警数和运营指标。Flink 可以持续聚合事件,并把结果写入 OLAP、搜索引擎或缓存供查询系统使用。

  • 实时 ETL 与 CDC

Flink 可持续读取消息或数据库变更日志,完成清洗、维表关联、格式转换和路由,再写入数据湖、数据仓库或下游消息系统。

  • 欺诈与异常检测

通过 Keyed State、定时器和复杂事件处理,可以识别短时间频繁交易、异常登录序列、设备状态变化等模式。

  • 事件驱动应用

Flink 可以维护用户、订单或设备的长期状态,根据事件持续更新状态并产生新事件,适合复杂业务规则和状态机。

  • 实时数仓

Flink SQL 与 CDC 可用于构建持续更新的分层数据模型。不过流式 SQL 的结果可能是 Changelog,而不是只追加的数据流,Sink 必须支持相应的 Append、Upsert 或更新语义。

十二、部署使用

  • 本地 Session Cluster
ruby 复制代码
//下载并解压与本机环境匹配的 Flink 发行包

//启动Session Cluster
./bin/start-cluster.sh

//运行示例程序
./bin/flink run \
  ./examples/streaming/TopSpeedWindowing.jar

//停止集群
./bin/stop-cluster.sh
  • Kubernetes Application Mode

应用 JAR 通常需要打入镜像或放到 JobManager 可访问的远程位置:

bash 复制代码
FROM flink:<固定版本>

RUN mkdir -p $FLINK_HOME/usrlib
COPY my-flink-job.jar $FLINK_HOME/usrlib/my-flink-job.jar

提交应用:

perl 复制代码
./bin/flink run \
  --target kubernetes-application \
  -Dkubernetes.cluster-id=my-flink-app \
  -Dkubernetes.container.image.ref=my-flink-image:<固定标签> \
  local:///opt/flink/usrlib/my-flink-job.jar

Kubernetes 环境还需要正确配置 ServiceAccount、RBAC、远程 Checkpoint Storage 和日志采集。

  • YARN Application Mode
arduino 复制代码
//配置 Hadoop Classpath
export HADOOP_CLASSPATH="$(hadoop classpath)"

//提交应用
./bin/flink run \
  -t yarn-application \
  ./my-flink-job.jar

生产环境还应核对 YARN 队列资源、ApplicationMaster 重试次数、用户 JAR 的 Classpath 顺序及 Hadoop 版本兼容性。

相关推荐
涛思数据(TDengine)1 小时前
从工业本体到 AI 原生:TDengine 出席 2026 QCon 分享工业数据基础设施路径
大数据·数据库·人工智能·tdengine·工业
Gu_WenYun2 小时前
从主题定价到订单定价:机器人基金的产业链观察
大数据·人工智能·金融
其实防守也摸鱼2 小时前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php
刀笔财经2 小时前
新时达的选择:先造血,再谈利润
大数据
Bode_20023 小时前
精益制造推行成熟度与核心量化评估体系
大数据·人工智能
超级新零售5 小时前
AI 零售软件是什么?从库存提醒到智能调货的系统分工
大数据·人工智能·零售
sun153690275726 小时前
基坑边坡监测:振弦式土压力计选型、安装埋设与数据采集方案
大数据·物联网·自动化
数字新视界7 小时前
机房动环监控系统在提升数据中心能效与安全中的应用探索
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
roman_日积跬步-终至千里7 小时前
零售与数仓(四):指标定义——从业务问题到可信计算
大数据·零售