其实官方文档中的对于Flink内存模型讲解的已经很详细了,本文主要是介绍下个人对这个内存模型的理解,如果有理解不对的地方,希望大家帮忙指正下!因为接触Flink的时间比较晚,所以一上来我们使用的就是V1.10版本,TaskManager的内存模型与配置在该版本中做了很大的优化。
Flink 1.10之前的的内存模型存在的缺点:
1. 流处理与批处理内存配置方法不同。比如Managed Memory这块内存,在批处理中有用,在流处理中使用不到的
2. 内存配置细节繁多,概念比较难懂,比如容器化会有专用的cutoff内存
3. RocksDB状态后端的内存不好配置(这部分个人没有理解,因为我们是使用的HDFS,没用RocksDB…)
个人对V1.10版本之前的内存模型只是想有个简单的了解,不打算做深入的研究了,反正我们项目中后续使用的都是V1.10之后的版本...
Flink 1.10版本内存模型:
Flink1.10版本内存模型架构如下图所示:
Total Process Memory对应Yarn/Mesos等容器化部署模式(需要用户指定),相当于申请容器的大小,Total Flink Memory对应standalone部署模式(需要用户指定)。
Total Flink Memory内部分成了:堆内内存 + 堆外内存:
堆内内存包括两部分:FreameWork Heap Memory(框架堆内存) + Task Heap Memory(任务堆内存)
堆外内存包含三部分:Managed Memory(托管内存) + Framework Off-heap Memory(框架堆外内存) + Network Memory(网络内存)
官网已经总结的很详细了:
组成部分 | 配置参数 | 描述 | 默认值 |
框架堆内存(Framework Heap Memory) | taskmanager.memory.framework.heap.size | 用于 Flink 框架的 JVM 堆内存(进阶配置)。 | 默认128M,不建议修改 |
任务堆内存(Task Heap Memory) | taskmanager.memory.task.heap.size | 用于 Flink 应用的算子及用户代码的 JVM 堆内存。 | 无默认值 不建议配置,Flink框架会使用Flink总内存-堆内框架内存-网络内存-托管内存得出。(按照默认值,肯定低于Flink总内存的50%) |
托管内存(Managed memory) | taskmanager.memory.managed.size taskmanager.memory.managed.fraction | 由 Flink 管理的用于排序、哈希表、缓存中间结果(批计算)以及 RocksDB State Backend 的本地内存(流计算)。受限Flink 总内存 | 无默认值 比例默认为0.4 |
框架堆外内存(Framework Off-heap Memory) | taskmanager.memory.framework.off-heap.size | 用于 Flink 框架的堆外内存(直接内存或本地内存)(进阶配置)。 | 默认128M,不建议修改 |
任务堆外内存(Task Off-heap Memory) | taskmanager.memory.task.off-heap.size | 用于 Flink 应用的算计及用户代码的堆外内存(直接内存或本地内存)。 | 默认是0 |
网络内存(Network Memory) | taskmanager.memory.network.min taskmanager.memory.network.max taskmanager.memory.network.fraction | 用于任务之间数据传输的直接内存(例如网络传输缓冲)。该内存部分为基于 Flink 总内存的受限的等比内存部分。 | 最小是64M 最大是1G 比例是0.1,最终计算出来的值会限制在64M~1G |
JVM Metaspace | taskmanager.memory.jvm-metaspace.size | Flink JVM 进程的 Metaspace。 | 默认256M |
JVM 开销 |
taskmanager.memory.jvm-overhead.min taskmanager.memory.jvm-overhead.max taskmanager.memory.jvm-overhead.fraction | 用于其他 JVM 开销的本地内存,例如栈空间、垃圾回收空间等。该内存部分为基于进程总内存的受限的等比内存部分。 | 最小192M 最大1G 比例是0.1 |
网络内存这部分和Flink反压有关,后续有时间单独开篇文章说一下,这一块个人觉得还是蛮重要的。
用户如何配置内存:
官网不建议同时设置进程总内存和 Flink 总内存。 这可能会造成内存配置冲突,从而导致部署失败。 额外配置其他内存部分时,同样需要注意可能产生的配置冲突。
要么配置进程总内存、要么配置Flink总内存、要么配置堆内内存+托管内存。个人觉得配置前两者比较靠谱,除非对Flink内部原理特别了解,否则没必要设置的那么细。
怎么判定TaskManager需要多少内存:
咨询了下边上对Flink比较了解的同事,Flink应用内存只要够用就行了,配过多性能也不会再往上提升了,但是怎么知道够用呢?
Flink中的数据全部存在状态中,即使是窗口的数据也存在窗口的State里面(这里面的数据不包括那些IO之间发来发去那些数据)。个人觉得可以这么搞,看CheckPoint的大小大概可以估算出State状态的大小,然后除以TaskManager的数量就大概可以知道每个TaskManager上保存的状态的大小,这部分用的JVM Heap中的Task Heap的大小,然后根据那个比例推测下整个Flink程序应该设置的大小。
但CheckPoint的大小也得是在实际环境中跑起来观察一下才能拿到。个人认为可以这么搞,拿家里的10W条数据做个试验,看下Checkpoint的大小,然后配置下内存。到现场之后,等比例进行一定的配置就可以了。
这样就可以大概估计下初始值,然后进行微调,或者还有一种野路子,直接拿少量的数据配置个比较大的内存,然后再按照上面的方法计算...好像这样还更加简单,哈哈哈
参考:
https://ci.apache.org/projects/flink/flink-docs-release-1.10/zh/ops/memory/mem_setup.html