flink-1.10 内存模型详解
文章目录
之前的一篇 文章(flink-1.10 如何配置 Task Executor 内存)介绍了新的内存模型下配置 task executor 内存的方法。可以与本文对照阅读。
本文则对 task executor 内存模型的所有组件进行详细说明。
1.概览
上图列出了所有的内存组件,每个组件都有对应的 flink 配置项,会相互影响各个组件的内存。
下表对应上图的各个组件。
组件 | 配置项 | 描述 |
---|---|---|
Framework Heap Memory | taskmanager.memory.framework.heap.size | (高级参数,一般不需要用户配置)分配给 Flink 框架的 JVM 堆内存(默认128MB) |
Task Heap Memory | taskmanager.memory.task.heap.size | 分配给 operator 和用户代码的 JVM 堆内存 |
Managed memory | taskmanager.memory.managed.size(默认none) taskmanager.memory.managed.fraction(默认0.4) |
被 flink 管理的本地内存,用于 batch 作业的中间结果排序(sort)、散列表(hash)、缓存(caching )和 Streaming 作业的 RocksDB state backend |
Framework Off-heap Memory | taskmanager.memory.framework.off-heap.size(默认128 mb) | (高级参数)分配给 Flink 框架的 Off-heap direct 内存 |
Task Off-heap Memory | taskmanager.memory.task.off-heap.size | 分配给 task operator 的 Off-heap direct 内存,默认(0 bytes) |
Network Memory | taskmanager.memory.network.min(默认64 mb) taskmanager.memory.network.max(默认1 gb) taskmanager.memory.network.fraction(默认0.1) |
为 tasks 之间的数据元素交换保留的 Off-heap direct(例如,通过网络进行传输的缓冲区),它是 Total Flink Memory 的一个有上下限的细分组件 |
JVM metaspace | taskmanager.memory.jvm-metaspace.size(默认96 mb ) | Flink JVM 进程的元数据空间大小,为本地内存 |
JVM Overhead | taskmanager.memory.jvm-overhead.min(默认192 mb) taskmanager.memory.jvm-overhead.max(默认1 gb) taskmanager.memory.jvm-overhead.fraction(默认0.1) |
为 JVM 进程预留的其他本地内存,用于线程栈、代码缓存、垃圾收集。它是 Total Process Memory(整个进程) 的一个有上下限的细分组件 |
如您所见,某些内存组件的大小可以通过相应的选项简单地设置。其他组件可以使用多个选项进行调优。
2.框架内存(Framework Memory)
Framework Memory 相关配置不要轻易更改,只有当我们确定 Flink 需要更多内存来处理内部数据结构或者操作时,才需要调整。这些配置与特定的部署环境或者作业结构有关,例如高并发(high parallelism)。此外,flink 的某些依赖,例如 hadoop 可能会再某些配置中消耗更多的直接或本地内存。注意
: 现在 Framework 和 task 的堆内存(及堆外内存)并没有隔离,两者处于同一个 JVM 堆(非堆)内存中。后续版本中会对两者进行隔离。
3.根据比例限制的组件(Capped Fractionated Components)
上一小节我们提到了两种根据比例限制的组件:
- Network memory: 是 Total Flink Memory 的某个比例
- JVM overhead:是 Total Process Memory 的某个比例
这些组件的大小必须在配置的 maximum 和 minimum 之间,否则 flink 启动时会抛出错误。maximum 和 minimum 有默认的配置,当然我们可以通过上一节提到的某些配置项进行人工配置。举个栗子,比如有以下配置:
- total Flink memory = 1000Mb,
- network min = 64Mb,
- network max = 128Mb,
- network fraction = 0.1
那么 Network memory 将是 1000Mb x 0.1 = 100Mb,在64-128Mb范围内。
当我们配置 network min 等于 network max 时,实际上此时 Network memory 的值就已经固定了,我们相当于显示的指定了 Network memory 就是这么大。
如果我们没有显示的配置组件内存,flink 会根据总内存的比例(fraction)来计算。计算出来的值再和配置的 max/min 值作比较,不能超出 max/min 的范围。再举个栗子,比如有以下配置:
- total Flink memory = 1000Mb,
- network min = 128Mb,
- network max = 256Mb,
- network fraction = 0.1
我们通过比例计算出是 100Mb(1000Mb x 0.1 = 100Mb),比 min 值还小,那么最终值是 min 值(128Mb)。
如果定义了总内存及其他组件的大小,也可能忽略 fraction 配置。在这种情况下,网络内存是其他组件分配完后总内存的剩余部分。计算出来的值仍然必须在 min/max 范围内,否则配置将失败。再举个栗子,比如只设置了以下内存选项:
- total Flink memory = 1000Mb,
- task heap = 100Mb,
- network min = 64Mb,
- network max = 256Mb,
- network fraction = 0.1
Total Flink Memory 的所有其他组件都有默认值,包括 managed memory fraction (0.4),我们计算出来其他组件的内存如下:
组件名 | 内存大小 |
---|---|
Framework Heap | 128mb |
Task Heap | 100mb |
managed memory | 400mb |
Framework Off-Heap | 128mb |
Task Off-Heap | 0 bytes |
总和 | 756mb |
剩余 min < 244 mb < max,将全部分配给 network。如果计算出来的值不再 min/max 范围内,flink 将启动失败。
4.对应的 JVM 参数(JVM Parameters)
flink taskexecutor 所有组件的内存配置和 JVM 参数的关系如下:
JVM Arguments | Value |
---|---|
-Xmx and -Xms | Framework + Task Heap Memory |
-XX:MaxDirectMemorySize | Framework + Task Off-Heap + Network Memory |
-XX:MaxMetaspaceSize | JVM Metaspace |
5.本地执行时的内存策略(Local Execution)
如果我们以本地模式启动 Flink ,例如通过 IDE 启动一个 java 进程,那么只有以下的配置生效:
内存组件 | 相关配置 | 本地模式下的默认值 |
---|---|---|
Task heap | taskmanager.memory.task.heap.size | infinite |
Task off-heap | taskmanager.memory.task.off-heap.size | infinite |
Managed memory | taskmanager.memory.managed.size | 128Mb |
Network memory | taskmanager.memory.network.min taskmanager.memory.network.max |
64Mb |
表格中的配置都有默认值,用户可以不用显示配置。infinite 代表 Long.MAX_VALUE bytes.
注意
:task heap 的配置与实际 JVM 进程中真实的堆大小毫无关系,它可能与下一个版本的优化有关。本地启动的 java 进程的实际 jvm 堆大小不受 flink 控制,而是与启动进程时的 JVM 参数(-Xmx、-Xms)相关。如果需要调节进程堆大小,需要我们显示的配置 JVM 参数(-Xmx、-Xms)。