内存模型详解

本文将详细介绍 Flink TaskExecutor 内存模型中的所有组成部分。 关于基本的内存配置方法,请参考配置指南

概述


Simple memory model


提示 任务堆外内存也包括了用户代码使用的本地内存(非直接内存)。

如上图所示,下表中列出了 Flink TaskExecutor 内存模型的所有组成部分,以影响其大小的相关配置参数。

  组成部分     配置参数     描述  
框架堆内存(Framework Heap Memory) taskmanager.memory.framework.heap.size 用于 Flink 框架的 JVM 堆内存(进阶配置)。
任务堆内存(Task Heap Memory) taskmanager.memory.task.heap.size 用于 Flink 应用的算子及用户代码的 JVM 堆内存。
托管内存(Managed memory) taskmanager.memory.managed.size
taskmanager.memory.managed.fraction
由 Flink 管理的用于排序、哈希表、缓存中间结果及 RocksDB State Backend 的本地内存。
框架堆外内存(Framework Off-heap Memory) taskmanager.memory.framework.off-heap.size 用于 Flink 框架的堆外内存(直接内存或本地内存)(进阶配置)。
任务堆外内存(Task Off-heap Memory) taskmanager.memory.task.off-heap.size 用于 Flink 应用的算计及用户代码的堆外内存(直接内存或本地内存)
网络内存(Network Memory) taskmanager.memory.network.min
taskmanager.memory.network.max
taskmanager.memory.network.fraction
用于任务之间数据传输的直接内存(例如网络传输缓冲)。该内存部分为基于 Flink 总内存受限的等比内存部分
JVM Metaspace taskmanager.memory.jvm-metaspace.size Flink JVM 进程的 Metaspace。
JVM 开销 taskmanager.memory.jvm-overhead.min
taskmanager.memory.jvm-overhead.max
taskmanager.memory.jvm-overhead.fraction
用于其他 JVM 开销的本地内存,例如栈空间、垃圾回收空间等。该内存部分为基于进程总内存受限的等比内存部分


我们可以看到,有些内存部分的大小可以直接通过一个配置参数进行设置,有些则需要根据多个参数进行调整。

框架内存

通常情况下,不建议对框架堆内存框架堆外内存进行调整。 除非你非常肯定 Flink 的内部数据结构及操作需要更多的内存。 这可能与具体的部署环境及作业结构有关,例如非常高的并发度。 此外,Flink 的部分依赖(例如 Hadoop)在某些特定的情况下也可能会需要更多的直接内存或本地内存。

提示 不管是堆内存还是堆外内存,Flink 中的框架内存和任务内存之间目前是没有隔离的。 对框架和任务内存的区分,主要是为了在后续版本中做进一步优化。

受限的等比内存部分

本节介绍下列内存部分的配置方法,它们都可以通过指定在总内存中所占比例的方式进行配置。

  • 网络内存:可以配置占用 Flink 总内存的固定比例
  • JVM 开销:可以配置占用进程总内存的固定比例

请同时参考概述部分

这些内存部分的大小必须在相应的最大值、最小值范围内,否则 Flink 将无法启动。 最大值、最小值具有默认值,也可以通过相应的配置参数进行设置。 例如,如果仅配置下列参数:

  • Flink 总内存 = 1000Mb
  • 网络内存最小值 = 64Mb
  • 网络内存最大值 = 128Mb
  • 网络内存占比 = 0.1

那么网络内存的实际大小将会是 1000Mb x 0.1 = 100Mb,在 64-128Mb 的范围内。

如果将最大值、最小值设置成相同大小,那相当于明确指定了该内存部分的大小。

如果没有明确指定内存部分的大小,Flink 会根据总内存和占比计算出该内存部分的大小。 计算得到的内存大小将受限于相应的最大值、最小。 例如,如果仅配置下列参数:

  • Flink 总内存 = 1000Mb
  • 网络内存最小值 = 128Mb
  • 网络内存最大值 = 256Mb
  • 网络内存占比 = 0.1

那么网络内存的实际大小将会是 128Mb,因为根据总内存和占比计算得到的内存大小 100Mb 小于最小值。

如果配置了总内存和其他内存部分的大小,那么 Flink 也有可能会忽略给定的占比。 这种情况下,受限的等比内存部分的实际大小是总内存减去其他所有内存部分后剩余的部分。 这样推导得出的内存大小必须符合最大值、最小值范围,否则 Flink 将无法启动。 例如,如果仅配置下列参数:

  • Flink 总内存 = 1000Mb,
  • 任务堆内存 = 100Mb,
  • 网络内存最小值 = 64Mb
  • 网络内存最大值 = 256Mb
  • 网络内存占比 = 0.1

Flink 总内存中所有其他内存部分均有默认大小(包括托管内存的默认占比)。 因此,网络内存的实际大小不是根据占比算出的大小(1000Mb x 0.1 = 100Mb),而是 Flink 总内存中剩余的部分。 这个剩余部分的大小必须在 64-256Mb 的范围内,否则将会启动失败。

JVM 参数

Flink 启动 TaskExecutor 进程时,会根据配置的和自动推导出的各内存部分大小,显式地设置以下 JVM 参数:

  JVM 参数       
-Xmx-Xms 框架堆内存 + 任务堆内存
-XX:MaxDirectMemorySize 框架堆外内存 + 任务堆外内存 + 网络内存
-XX:MaxMetaspaceSize JVM Metaspace


请同时参考概述部分

本地执行

如果你是将 Flink 作为一个单独的 Java 程序运行在你的电脑本地而非创建一个集群(例如在 IDE 中),那么只有下列配置会生效,其他配置参数则不会起到任何效果:

  组成部分     配置参数     本地执行时的默认值  
任务堆内存 taskmanager.memory.task.heap.size 无穷大
任务堆外内存 taskmanager.memory.task.off-heap.size 无穷大
托管内存 taskmanager.memory.managed.size 128Mb
网络内存 taskmanager.memory.network.min
taskmanager.memory.network.max
64Mb


本地执行模式下,上面列出的所有内存部分均可以但不是必须进行配置。 如果未配置,则会采用默认值。 其中,任务堆内存任务堆外内存的默认值无穷大(Long.MAX_VALUE字节),以及托管内存的默认值 128Mb 均只针对本地执行模式。

提示 这种情况下,任务堆内存的大小与实际的堆空间大小无关。 该配置参数可能与后续版本中的进一步优化相关。 本地执行模式下,JVM 堆空间的实际大小不受 Flink 掌控,而是取决于本地执行进程是如何启动的。 如果希望控制 JVM 的堆空间大小,可以在启动进程时明确地指定相关的 JVM 参数,即 -Xmx-Xms.