flink的架构
Apache Flink 是一个分布式、高性能的流处理芯片,用于对无界和有界数据流进行有状态计算。
Flink 的架构设计非常优秀,具有高吞吐、低延迟、精确一次(Exactly-Once)一致性保证以及高可用性。
要深入理解 Flink 的架构,我们可以从 运行时角色(进程级架构)、核心组件功能、任务执行图演变、内存模型 和 容错机制 这五个维度来进行剖析。
一、 运行时角色(Runtime Architecture)
Flink 采用典型的 Master-Slave(主从) 架构。它主要由两种类型的进程组成:一个 JobManager(Master)和多个 TaskManager(Worker)。
plaintext
+-------------------+
| Client | (提交 JobGraph)
+---------+---------+
|
v
+-----------------------------------+
| JobManager | (Master 节点)
| +------------+ +------------+ |
| | Dispatcher | | Resource | |
| +------------+ | Manager | |
| +------------+ +------------+ |
| | JobMaster | |
| +------------+ |
+--------+-----------------+--------+
| |
(分配 Slot) | | (分配 Slot)
v v
+---------+-------+ +-----+---------+
| TaskManager | | TaskManager | (Worker 节点)
| +-----------+ | | +-----------+ |
| | Task Slot | | | | Task Slot | |
| +-----------+ | | +-----------+ |
| | Task Slot | | | | Task Slot | |
| +-----------+ | | +-----------+ |
+-----------------+ +-----------------+
1. Client(客户端)
- 作用:不是 Flink 运行时的组成部分,但负责准备和发送数据流。
- 职责:将用户写的代码(DataStream API, Table/SQL)编译成 JobGraph(作业图),然后提交给 JobManager。
2. JobManager(协调者/Master)
控制一个 Flink 集群的主进程,它包含三个核心组件:
- Dispatcher(分发器):
- 提供 REST 接口,负责接收 Client 提交的 JobGraph。
- 为每个新提交的作业启动一个新的 JobMaster。
- 提供 Web UI 展示集群运行状态。
- ResourceManager(资源管理器):
- 负责管理集群中的资源(主要是 TaskManager 的 Task Slots)。
- 适配不同的资源管理平台(如 YARN、Kubernetes、Standalone)。当 Slot 不足时,向底层平台申请新的容器。
- JobMaster(作业管理器):
- 每个作业(Job)都有一个独立的 JobMaster。
- 将 JobGraph 转换成物理执行计划 ExecutionGraph。
- 向 ResourceManager 申请运行任务所需的 Slot。
- 调度 Task 的执行,并协调 Checkpoint(检查点)的制作。
3. TaskManager(执行者/Worker)
- 作用:实际执行 Task 的工作进程。
- 职责:
- 向 ResourceManager 注册自己的 Slot。
- 接收 JobMaster 分配的 Task 并执行。
- 负责同级 TaskManager 之间的数据交换(Data Exchange)。
二、 核心概念:Task Slot(任务槽)与并行度
1. Task Slot
- TaskManager 是一个 JVM 进程。为了控制并发执行的 Task 数量,TaskManager 将自己的内存划分为多个 Task Slot(任务槽)。
- 资源隔离:Slot 之间仅隔离内存,不隔离 CPU。例如,一个拥有 3 个 Slot 的 TaskManager 会将其托管内存(Managed Memory)平均分成 3 份给每个 Slot 独立使用。
2. Slot Sharing(槽共享)
- Flink 允许同一个作业中不同任务的子任务(Subtask)共享同一个 Slot(前提是它们属于不同的算子阶段,比如一个是 FlatMap,一个是 KeyBy-Sink)。
- 好处:
- 极大地提高了资源利用率,避免了某些极度消耗资源的算子独占 Slot,而轻量算子闲置。
- 简化了并行度的配置:一个作业所需的总 Slot 数,就等于该作业中最大算子的并行度(Parallelism)。
三、 任务执行图的演变(Graph-Concept)
Flink 会在不同的阶段将用户的代码转换成不同的“图”(Graph),最终落地为分布式执行的任务:
plaintext
StreamGraph (DataStream API)
| (Client 端生成)
v
JobGraph (优化:算子链合并 Operator Chaining)
| (Client 提交给 JobManager)
v
ExecutionGraph (并行化、实例化)
| (JobMaster 调度)
v
Physical Graph (分配到 TaskManager 上的 Task)
- StreamGraph:根据用户代码直接生成的拓扑图,表达算子之间的逻辑关系。
- JobGraph:Client 端对 StreamGraph 优化后的图。最核心的优化是 Operator Chaining(算子链合并)。
- 注:将没有 Shuffle 的相邻算子(如 Source -> Map)合并成一个 Operator Chain,放入同一个线程执行,减少线程切换和序列化开销。
- ExecutionGraph:JobMaster 将 JobGraph 转化为可并行执行的图,是 JobGraph 的并行版本,包含了每个 Task 的多个并发实例(Subtask)以及它们之间的连接。
- 物理执行图(Physical Graph):并非真实的数据结构,而是 JobMaster 将 Task 分发到各个 TaskManager 的 Slot 中后,实际在集群中运行的线程状态。
四、 状态管理与容错架构(State & Checkpoint)
Flink 最强大的地方在于它的有状态计算(Stateful Computation)和Exactly-Once 容错机制。
1. 状态后端(State Backend)
状态(State)是指计算过程中的中间结果(如聚合值、窗口数据)。Flink 提供两种主要的状态存储方式:
- HashMapStateBackend(内存型):状态存储在 TaskManager 的 JVM 堆内存中。读写极快,但受限于内存大小。
- EmbeddedRocksDBStateBackend(磁盘型):状态存储在开辟的本地 RocksDB(KV 数据库)中。可以利用磁盘,支持超出内存大小的超大状态,但读写性能略逊。
2. Checkpoint 机制(检查点)
Flink 内部使用 Chandy-Lamport 算法 的变体(异步屏障快照 ABS)来实现一致性快照:
- JobManager 的 Checkpoint Coordinator 定期向数据源(Source)插入 Barrier(屏障)。
- Barrier 随着数据流向下游移动。
- 当算子收到 Barrier 时,会将其当前的状态做一次快照,并异步持久化到分布式存储(如 HDFS / S3)中。
- 如果作业崩溃,Flink 会从最近一次成功的 Checkpoint 恢复所有算子的状态,并重放自该 Checkpoint 以来的数据,从而实现 Exactly-Once(精准一次) 的语义。
五、 部署模式(Deployment Modes)
Flink 架构支持多种部署模式,决定了 JobManager 的生命周期以及集群资源的共享方式:
- Application Mode(应用模式 - 推荐):
- Client 的 main 方法在 JobManager 上运行,而不是在本地。
- 每个作业独享一个 JobManager,作业结束,集群销毁。
- 优点:对客户端友好,省带宽,适合生产环境 K8s/YARN。
- Per-Job Mode(单作业模式):
- Client 在本地解析生成 JobGraph。
- 为每个作业向资源框架(YARN/K8s)申请一个专属集群。作业结束,集群销毁。
- Session Mode(会话模式):
- 预先启动一个临时的 Flink 集群(JobManager 和 TaskManager 长期运行)。
- 多个作业共享这个集群的资源。
- 缺点:作业之间资源不隔离,一个作业崩溃可能影响其他作业。
总结
Flink 的架构核心可以总结为:基于 Master-Slave 架构,利用 Task Slot 隔离内存资源,通过 Operator Chaining 优化执行效率,依赖 Barrier 机制 实现轻量级 Checkpoint,从而在分布式流处理领域达到了极高的性能与可靠性标准。