Flink TM、subTask、JVM、算子链、slot、slot组的关系

94 阅读3分钟

1.TaskManager与JVM

  1. TaskManager是根据Flink集群分配的,本地测试LocalExecutionEnvironment默认只会产生一个TaskManager。
  2. 一个TaskManager对应一个JVM,不同的TaskManger是不同的JVM,完全隔离。(同一个JVM的静态变量会共享)
    • 同一JVM内的资源(静态变量、类加载器、数据库连接池等)可被所有Subtask共享;
    • 不同JVM间无任何内存共享,需通过Flink分布式状态(如RocksDB)或外部存储(如Redis)传递数据。

2.算子链Operator Chain

  1. 算子链(Operator Chain)的形成需满足以下
    • 两个算子的并行度相同
    • 后一个算子的输入仅来自前一个算子(无其他上游算子);
    • 两个算子处于同一 Slot 共享组(默认都是default组);
    • 前一个算子到后一个算子的连接无重分区操作(如keyByrebalanceshuffle等会打破算子链,forward连接则允许)。

3.TaskManger的Slot与subTask

  1. 一个TaskManager下会有多个slot,这些slot是可以共享TaskManager内存的(数据结构、对象、变量等)。但每个Slot也有自己独立的执行上下文和一定的资源隔离,并不是完全无限制地共享所有内存。
  2. slot是TaskManager中用于并行执行任务的资源单位,每个slot可以运行一个|多个任务
  3. subtask与Slot的关系
    • subtask是“算子的并行执行实例”(如并行度3的Map算子对应3个MapSubtask),subTask本质是一个Java对象;
    • subtask运行在Slot上,一个Slot可运行多个subtask(需满足:① 来自同一作业;② 处于同一Slot共享组;③ 无资源配额冲突);
    • 核心对应关系:当前算子的Subtask数量 = 该算子的并行度image.png
  4. Slot 是 TM 的 “资源切片”,其 “资源隔离” 并非 “内存完全隔离”,而是 “资源配额隔离”
    • 共享的资源:TM 的 JVM 堆内存、堆外内存、类加载器、静态资源(如数据库连接池实例);
    • 隔离的资源:Flink 通过配置为每个 Slot 分配固定的内存配额(如taskmanager.memory.task.heap.size)、CPU 权重,避免单个 Slot 耗尽 TM 的全部资源。

4.slot组

  1. slot组是逻辑隔离机制,通过算子.slotSharingGroup("group-name")指定,目的是将高负载算在单独放在一个组内,避免被其他算子抢占资源。
  2. 调度规则:不同Slot组的任务必须分配到独立的Slot;同一Slot组的任务可共享Slot(默认default组,实现资源复用)。
  3. 内存共享的核心依据是是否属于同一个TaskManager
    • 同一 TM 内的所有 Slot(无论是否同组):共享 TM 的 JVM 内存(如静态变量、共享对象);
    • 不同 TM 的 Slot(无论是否同组):不共享内存(JVM 隔离)。
  4. 不同slot组的,但在同一个TaskManager下的slot之间,共享变量的规则如下:
    • 如果Map是全局静态变量,那么在同一个TaskManager下的所有slot都可以访问和修改
    • 如果Map是在 TaskManager 的初始化阶段open()创建且被所有 Slot 共享,那么不同 Slot 组的 Slot 也可以共享这个Map
    • 如果Map是在每个 Slot 内部单独创建的,那么不同 Slot 组的 Slot 各自拥有独立的Map实例,它们之间不会共享.

5.slot、TM数量计算

  1. 所需总slot的数量=每个slot组的最大并行度的总和
  2. TM数量=ceil(所需总slot的数量/每个TM配置的slot数)