Flink 基础回顾:架构、核心概念与运行模式
好,咱们正式开始第 2 章。在动手搭建 CDC 管道之前,我觉得有必要先把 Flink 的底子夯实一下。你想想看,后面所有的实时同步、状态计算、容错恢复,全都跑在 Flink 上。如果对它的架构和核心概念模棱两可,后面调试起来会非常痛苦。
我个人习惯把 Flink 理解成一个「有状态的分布式数据流引擎」。它不像 Spark 那样以批处理起家,Flink 天生就是为流而生。这一点很重要,因为它决定了整个框架的设计哲学。
Flink 架构:主从模型与组件分工
Flink 的运行时架构,说白了就是一套主从模式。一个集群里有一个「大脑」和一堆「工人」。
核心组件一览:
- JobManager(主节点):负责接收作业、调度任务、协调检查点。它里面有三个关键角色:Dispatcher(接收提交)、JobMaster(管理单个作业)、ResourceManager(分配资源)。
- TaskManager(从节点):真正干活的进程。每个 TaskManager 有多个 Task Slot,Slot 是资源调度的最小单位。
- Client:提交作业的入口,提交完可以退出(Session 模式)或保持连接(Per-Job 模式)。
我记得刚接触 Flink 时,总搞不清 Slot 和并行度的关系。后来踩过一次坑才明白:Slot 是静态资源划分,并行度是动态逻辑并发。一个 TaskManager 有 4 个 Slot,不代表你只能跑 4 并行度——你可以跑 8 并行度,但 Slot 不够时会排队或跨 TM 调度。
核心概念:DataStream、Operator、Source、Sink
这四个概念,是 Flink 编程模型的基石。说白了,你写 Flink 作业就是在组装这四样东西。
DataStream
DataStream 是 Flink 中表示无限数据流的核心抽象。它不只是一个集合,它背后绑定着并行度、分区策略、时间语义和状态。我习惯把它想象成「一条流动的数据带」,每个元素都带着自己的时间戳。
我的经验:在 CDC 场景下,DataStream 里流动的是变更事件(Insert/Update/Delete)。每条记录都包含 before 和 after 字段,以及操作类型。你处理时一定要区分清楚,否则下游数据会乱。
Operator(算子)
Flink 提供了丰富的算子,我按使用频率排个序:
| 算子 | 用途 | CDC 场景常见用法 |
|---|---|---|
| map | 一对一转换 | 将 Debezium 的 JSON 解析为 POJO |
| flatMap | 一对多转换 | 将一条变更拆成多条下游消息 |
| keyBy | 按 key 分区 | 按表名或主键分区,保证同一条记录有序 |
| filter | 过滤 | 只保留特定表的变更事件 |
| window | 窗口聚合 | 统计每分钟的变更量(监控用) |
| process | 带状态的灵活处理 | 实现精确一次的去重或合并 |
嗯,这里要注意:keyBy 之后才能使用 keyed state。如果你不做 keyBy,只能用 operator state,那在 CDC 场景下做按主键的去重就会很麻烦。
Source(数据源)
Source 是数据的入口。Flink 内置了很多 Source,但 CDC 场景下我们主要用两类:
- Kafka Source:从 Kafka 消费 Debezium 的变更事件。支持 exactly-once 语义,配合 offset 提交。
- 自定义 Source:比如直接连接 MySQL binlog 的 Flink CDC Connector(基于 Debezium 封装)。
我曾经踩过的坑:用 Kafka Source 时,如果并行度大于 Kafka 分区数,会有部分 TaskManager 空闲。反过来,并行度小于分区数,一个 TaskManager 要消费多个分区,压力会集中。建议 Source 的并行度 = 分区数。
Sink(数据输出)
Sink 是数据的出口。在实时管道里,Sink 的选择直接决定了端到端的延迟和一致性:
- Kafka Sink:最常用,把处理后的变更事件写回 Kafka,供下游消费。
- JDBC Sink:直接写入数据库,但要注意事务和幂等性。
- HBase/Redis Sink:适合维表关联或状态缓存。
我个人习惯在 Sink 前加一个 map 算子做格式校验,避免脏数据污染下游。这个习惯帮我省了好几次凌晨 OnCall 的麻烦。
Flink 运行模式
Flink 支持三种部署模式,我直接给你对比清楚:
| 模式 | 集群生命周期 | 资源隔离 | 适用场景 |
|---|---|---|---|
| Session 模式 | 共享集群,作业动态提交 | 弱(作业间争抢 Slot) | 开发测试、小作业 |
| Per-Job 模式 | 每个作业启动独立集群 | 强(资源独享) | 生产环境、重要作业 |
| Application 模式 | Main 方法在集群执行 | 强(资源独享) | 大规模作业、CI/CD 部署 |
为什么会有 Application 模式?你想想看,Per-Job 模式下 Client 需要一直保持连接,如果 Client 挂了,作业虽然还在跑,但你没法做后续操作了。Application 模式把 Main 方法提交到集群里执行,Client 提交完就可以退出,干净利落。
我的建议:生产环境的 CDC 管道,优先选 Application 模式。资源隔离好,运维也简单。Session 模式只适合你本地调试时用,别上生产。
另外,Flink 还支持多种资源管理平台:YARN、Kubernetes、Standalone。我个人强烈推荐 Kubernetes,弹性伸缩和故障恢复都比 YARN 强太多。后面章节我们会专门讲 K8s 上的 Flink 部署。
好了,Flink 的基础就回顾到这里。这些概念在后面构建 CDC 管道时会反复用到,尤其是 DataStream 的 keyBy 和状态管理,是保证数据一致性的关键。咱们接着往下走。