← 返回文章列表

Flink 底层原理系列(二):运行时架构

2021-01-12·5 分钟阅读

前言

理解 Flink 的运行时架构对于优化作业性能和排查问题至关重要。本章将深入解析 Task Slot、Slot Sharing、作业调度以及执行图的转换过程。

技术亮点

技术点难度面试价值本文覆盖
Task Slot⭐⭐⭐高频考点
Slot Sharing⭐⭐⭐⭐高频考点
执行图层级⭐⭐⭐⭐进阶考点
作业调度⭐⭐⭐实战价值

面试考点

  1. Task Slot 是什么?为什么需要 Slot?
  2. 什么是 Slot Sharing?有什么好处?
  3. Flink 的执行图有哪几个层级?
  4. Flink 如何调度任务?

Task Slot 详解

Slot 概念

┌─────────────────────────────────────────────────────────────────────────┐
│                        Task Slot 概念                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Task Slot 是 Flink 中资源隔离的基本单位:                               │
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  TaskManager (12GB 内存, 4 CPU, 4 Slots)                       │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  Slot 1 (3GB)    Slot 2 (3GB)    Slot 3 (3GB)    Slot 4 (3GB)│ │
│  │  │  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐│ │   │
│  │  │  │   Task    │  │   Task    │  │   Task    │  │   Task    ││ │   │
│  │  │  │  Chain    │  │  Chain    │  │  Chain    │  │  Chain    ││ │   │
│  │  │  │  A+B+C    │  │  D+E+F    │  │  G+H+I    │  │  J+K+L    ││ │   │
│  │  │  └───────────┘  └───────────┘  └───────────┘  └───────────┘│ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  Slot 的特点:                                                          │
│  • 资源隔离:每个 Slot 拥有独立的内存资源                               │
│  • CPU 共享:同一 TaskManager 的 Slot 共享 CPU                         │
│  • 内存分配:TaskManager 内存按 Slot 数量均分                           │
│  • 独立任务:一个 Slot 可以执行一个完整的 Operator Chain                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Slot 的作用

┌─────────────────────────────────────────────────────────────────────────┐
│                        Slot 的作用                                       │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  1. 资源隔离                                                            │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  • 不同作业/任务之间内存隔离                                    │   │
│  │  • 防止一个任务耗尽整个 TaskManager 内存                        │   │
│  │  • 提供稳定的资源保证                                           │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  2. 并行度控制                                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  作业并行度 = 该作业占用的 Slot 数量                            │   │
│  │                                                                 │   │
│  │  示例:并行度 4 的作业需要 4 个 Slot                            │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  3. 资源利用优化                                                        │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  • 多个 Operator 可以共享同一个 Slot                            │   │
│  │  • 减少 JVM 进程数量                                            │   │
│  │  • 减少 TCP 连接和网络开销                                      │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Slot Sharing

Slot Sharing 原理

┌─────────────────────────────────────────────────────────────────────────┐
│                        Slot Sharing 原理                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  无 Slot Sharing(每个 Operator 独占 Slot):                            │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  Source(2) ──► Map(2) ──► Filter(2) ──► Sink(2)                │   │
│  │       │           │           │           │                     │   │
│  │       ▼           ▼           ▼           ▼                     │   │
│  │   ┌──────┐    ┌──────┐    ┌──────┐    ┌──────┐                │   │
│  │   │Slot 1│    │Slot 3│    │Slot 5│    │Slot 7│                │   │
│  │   │Slot 2│    │Slot 4│    │Slot 6│    │Slot 8│                │   │
│  │   └──────┘    └──────┘    └──────┘    └──────┘                │   │
│  │                                                                 │   │
│  │  需要 8 个 Slot!资源利用率低                                    │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                              │                                          │
│                              ▼ Slot Sharing                             │
│  有 Slot Sharing(Operator Chain 共享 Slot):                           │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  Source(2) ──► Map(2) ──► Filter(2) ──► Sink(2)                │   │
│  │       │           │           │           │                     │   │
│  │       └───────────┴───────────┴───────────┘                     │   │
│  │                       │                                         │   │
│  │                       ▼                                         │   │
│  │              ┌────────────────┐                                 │   │
│  │              │ Slot 1: S+M+F+Si│                                │   │
│  │              │ Slot 2: S+M+F+Si│                                │   │
│  │              └────────────────┘                                 │   │
│  │                                                                 │   │
│  │  只需要 2 个 Slot!资源利用率高                                  │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  Slot Sharing 的好处:                                                  │
│  • 减少资源占用                                                         │
│  • 减少网络通信(Operator Chain 内部本地转发)                          │
│  • 提高资源利用率                                                       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Operator Chain

┌─────────────────────────────────────────────────────────────────────────┐
│                        Operator Chain                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Operator Chain 是将多个 Operator 合并为一个 Task执行单元:              │
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  Chain 条件:                                                   │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  1. Forward 连接(一对一,不重分区)                        │ │   │
│  │  │  2. 并行度相同                                             │ │   │
│  │  │  3. 没有禁用 Chain(startNewChain/disableChain)           │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                                                                 │   │
│  │  Chain 示例:                                                   │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  [Source] ──► [Map] ──► [Filter] ──► [KeyBy] ──► [Sink]  │ │   │
│  │  │     │          │          │            │           │      │ │   │
│  │  │     └──────────┴──────────┘            └───────────┘      │ │   │
│  │  │            │                              │                │ │   │
│  │  │            ▼                              ▼                │ │   │
│  │  │       Chain 1                         Chain 2              │ │   │
│  │  │   (Source+Map+Filter)            (KeyBy+Sink)             │ │   │
│  │  │                                                           │ │   │
│  │  │  KeyBy 导致数据重分区,因此不能与前一个 Chain 合并         │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  Chain 好处:                                                           │
│  • 减少线程切换开销                                                     │
│  • 减少序列化/反序列化                                                  │
│  • 减少网络传输                                                         │
│  • 提高性能                                                             │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

执行图层级

四层执行图

┌─────────────────────────────────────────────────────────────────────────┐
│                        四层执行图转换                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  1. StreamGraph(用户逻辑图)                                   │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  • 用户通过 DataStream API 构建的逻辑图                    │ │   │
│  │  │  • 每个 Operator 对应一个 StreamNode                       │ │   │
│  │  │  • 包含转换逻辑和用户函数                                   │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                         │                                       │   │
│  │                         ▼ StreamGraph -> JobGraph               │   │
│  │  2. JobGraph(作业图)                                          │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  • Operator Chain 合并为一个 JobVertex                     │ │   │
│  │  │  • 包含序列化后的用户函数                                   │ │   │
│  │  │  • JobVertex 之间通过 IntermediateDataSet 连接             │ │   │
│  │  │  • 是提交给 JobManager 的数据结构                          │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                         │                                       │   │
│  │                         ▼ JobGraph -> ExecutionGraph            │   │
│  │  3. ExecutionGraph(执行图)                                    │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  • JobVertex 展开为 ExecutionJobVertex                     │ │   │
│  │  │  • 每个并行度对应一个 ExecutionVertex                       │ │   │
│  │  │  • 包含状态管理和调度信息                                   │ │   │
│  │  │  • 是 JobMaster 管理的核心数据结构                         │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                         │                                       │   │
│  │                         ▼ ExecutionGraph -> Physical Graph      │   │
│  │  4. Physical Graph(物理执行图)                                │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  • ExecutionVertex 映射到具体的 TaskManager                │ │   │
│  │  │  • 包含实际的部署信息                                       │ │   │
│  │  │  • TaskManager 执行的基本单位                               │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

图转换示例

┌─────────────────────────────────────────────────────────────────────────┐
│                        图转换示例                                        │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  用户代码:                                                              │
│  env.addSource(new MySource())                                         │
│      .map(new MyMap())                                                 │
│      .keyBy(x -> x.key)                                                │
│      .sum("value")                                                     │
│      .addSink(new MySink());                                           │
│                                                                         │
│  StreamGraph:                                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  [Source] ──► [Map] ──► [KeyBy] ──► [Sum] ──► [Sink]           │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  JobGraph(并行度=2,Chain 优化后):                                    │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  JobVertex 1                    JobVertex 2                     │   │
│  │  ┌──────────────────┐          ┌──────────────────┐            │   │
│  │  │ Source + Map     │          │ KeyBy + Sum + Sink│            │   │
│  │  │ (parallelism=2)  │─────────►│ (parallelism=2)  │            │   │
│  │  └──────────────────┘          └──────────────────┘            │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  ExecutionGraph:                                                       │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  ExecutionJobVertex 1           ExecutionJobVertex 2            │   │
│  │  ┌──────────────────┐          ┌──────────────────┐            │   │
│  │  │ ExecutionVertex 0│          │ ExecutionVertex 0│            │   │
│  │  │ ExecutionVertex 1│─────────►│ ExecutionVertex 1│            │   │
│  │  └──────────────────┘          └──────────────────┘            │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

作业调度

调度策略

┌─────────────────────────────────────────────────────────────────────────┐
│                        作业调度策略                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Flink 支持两种调度模式:                                               │
│                                                                         │
│  1. Eager 调度(立即调度)                                              │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  • 流作业默认模式                                               │   │
│  │  • 所有任务同时启动                                             │   │
│  │  • 需要足够的资源                                               │   │
│  │                                                                 │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  任务 A ──► 任务 B ──► 任务 C                              │ │   │
│  │  │    │          │          │                                 │ │   │
│  │  │    ▼          ▼          ▼                                 │ │   │
│  │  │  全部同时启动                                              │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  2. Lazy 调度(延迟调度)                                               │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │  • 批作业默认模式                                               │   │
│  │  • 上游有数据时才启动下游                                       │   │
│  │  • 节省资源                                                     │   │
│  │                                                                 │   │
│  │  ┌───────────────────────────────────────────────────────────┐ │   │
│  │  │                                                           │ │   │
│  │  │  任务 A ──► 任务 B ──► 任务 C                              │ │   │
│  │  │    │                                                     │ │   │
│  │  │    ▼                                                     │ │   │
│  │  │  先启动 A                                                 │ │   │
│  │  │    │                                                     │ │   │
│  │  │    ▼ A 完成后                                             │ │   │
│  │  │  启动 B                                                   │ │   │
│  │  │    │                                                     │ │   │
│  │  │    ▼ B 完成后                                             │ │   │
│  │  │  启动 C                                                   │ │   │
│  │  │                                                           │ │   │
│  │  └───────────────────────────────────────────────────────────┘ │   │
│  │                                                                 │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

任务状态

┌─────────────────────────────────────────────────────────────────────────┐
│                        任务状态流转                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                 │   │
│  │          ┌──────────────┐                                      │   │
│  │          │   CREATED    │                                      │   │
│  │          └──────┬───────┘                                      │   │
│  │                 │                                               │   │
│  │                 ▼                                               │   │
│  │          ┌──────────────┐                                      │   │
│  │          │  SCHEDULED   │                                      │   │
│  │          └──────┬───────┘                                      │   │
│  │                 │                                               │   │
│  │                 ▼                                               │   │
│  │          ┌──────────────┐                                      │   │
│  │          │  DEPLOYING   │                                      │   │
│  │          └──────┬───────┘                                      │   │
│  │                 │                                               │   │
│  │        ┌────────┴────────┐                                     │   │
│  │        ▼                 ▼                                     │   │
│  │ ┌──────────────┐  ┌──────────────┐                            │   │
│  │ │   RUNNING    │  │   FAILED     │                            │   │
│  │ └──────┬───────┘  └──────────────┘                            │   │
│  │        │                                                       │   │
│  │        ├──────────────────────┐                               │   │
│  │        ▼                      ▼                               │   │
│  │ ┌──────────────┐       ┌──────────────┐                      │   │
│  │ │  FINISHED    │       │  CANCELING   │                      │   │
│  │ └──────────────┘       └──────┬───────┘                      │   │
│  │                               │                               │   │
│  │                               ▼                               │   │
│  │                        ┌──────────────┐                      │   │
│  │                        │   CANCELED   │                      │   │
│  │                        └──────────────┘                      │   │
│  │                                                               │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  状态说明:                                                             │
│  • CREATED:任务创建                                                    │
│  • SCHEDULED:任务已调度,等待资源                                      │
│  • DEPLOYING:任务部署中                                                │
│  • RUNNING:任务运行中                                                  │
│  • FINISHED:任务正常结束                                               │
│  • CANCELING/CANCELED:任务取消中/已取消                                │
│  • FAILED:任务失败                                                     │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

总结

本章深入解析了 Flink 运行时架构:

概念说明
Task Slot资源隔离的基本单位,内存独立,CPU 共享
Slot Sharing多个 Operator Chain 共享 Slot,提高资源利用率
Operator Chain合并多个 Operator 为一个 Task,减少开销
执行图StreamGraph → JobGraph → ExecutionGraph → Physical Graph

参考资料

下一章预告

下一章将深入解析 数据流模型,包括:

  • DataStream API 设计
  • Transformation 与 Operator
  • 数据交换模式
分享: