Flink 内存模型
在大数据中所有开源计算框架都会使用到JVM ,例如:MapReduce、Storm、Spark等,这些计算框架在处理数据过程中涉及到将大量数据存储在内存中,此时如果内存管理过渡依赖JVM,就会出现java对象存储密度低导致内存使用率低以及垃圾回收导致系统不稳定问题,这极大影响了系统的性能和稳定性。Flink也是计算框架,计算过程中同样也是基于JVM,但是Flink实现了内存管理,即脱离JVM对内存进行管理,统一且有效地管理堆内存和堆外内存,确保大规模数据处理不会因为GC等问题造成系统不稳定。
Flink1.10版本后为了满足更细粒度以及灵活的内存管理,升级了内存模型,对内存组成进行了比较大的调整,由于在Flink中计算主要存在于TaskManager节点,这里说的Flink内存模型也就是TaskManager的内存模型,JobManager的内存模型与TaskManager的内存模型类似。
上图是Flink内存模型,从图中可以看出Flink 进程总内存(Total Process Memory)包含了Flink总内存(Total Flink Memory)和JVM特定内存。Flink总内存又包括JVM堆内存(JVM Heap)、托管内存(Managed Memory) 、直接内存(Direct Memory)。下面分别介绍各个部分内存功能以及参数配置。
Flink 总内存(Total Flink Memory)
TaskManager进程占用的所有与Flink相关的内存,不包括JVM特定内存部分,包含6个部分内存(Framework堆内存、Task堆内存、托管内存、Framework非堆内存、Task非堆内存、Network),关于Flink Framework和Flink Task使用的内存既有堆内内存也有堆外内存,托管内存和Network使用的仅是堆外内存。
Flink总内存配置参数根据不同的部署场景不同:taskmanager.memory.flink.size 或者 taskmanager.memory.process.size(容器部署指定参数),无默认值,需要用户指定。
Flink堆内存(JVM Heap)
Flink堆内存就是JVM堆内存(JVM Heap),分为Framework堆内存(Framework Heap)和Task堆内存(Task Heap),其中Framework 主要用于Flink框架本身需要的内存空间,Task堆内存则用于Flink算子及用户代码的执行,也被称为TaskExecutor使用的内存,两者的主要区别在于是否将内存计入Slot计算资源中,Framework堆内存不会将内存分配给Slot,Task堆内存会分配给Slot。
Framework堆内存(Framework Heap)
Framework堆内存配置参数为:taskmanager.memory.framework.heap.size,该值默认为128M。
Task 堆内存(Task Heap)
非堆内存也可以叫做堆外内存,更准确来说是大部分的堆外内存,包含了托管内存(Managed Memory)、直接内存(Direct Memory)两部分。
Flink非堆内存(Off-Heap Memory)
直接内存(Direct Memory)
直接内存(Direct Memory)分为Framework非堆内存(Framework Off-Heap)、Task 非堆内存(Task Off-Heap)和Network三个部分。直接内存主要作用是减少GC压力、提升性能效率。
Framework非堆内存(Framework Off-Heap)
Framework 非堆内存即taskexecutor的Framework 堆外内存大小,不会分配给slot,配置参数为:taskmanager.memory.framework.off-heap.size,默认值128M。
Task非堆内存(Task Off-Heap)
Task非堆内存,配置参数taskmanager.memory.task.off-heap.size,默认值为0,即不使用。
Network
Network内存存储空间主要用于基于Netty进行网络数据交换数据传输的本地缓存,例如:TaskManager之间Shuffle、广播、与外部组件的数据传输。Network的配置相关参数有3个,分别如下:
taskmanager.memory.network.min:网络缓存的最小值,默认64MB;
taskmanager.memory.network.max:网络缓存的最大值,默认1GB;
taskmanager.memory.network.fraction:网络缓存占Flink总内存taskmanager.memory.flink.size的比例,默认值0.1。若根据此比例算出的内存量比最小值小或比最大值大,就会限制到最小值或者最大值。
JVM 特定内存
JVM特定内存是JVM堆外内存的另一小部分内存,其不在Flink总内存范围之内,包括JVM元空间(JVM Metaspace)和JVM Overhead 两部分,其中JVM元空间存储JVM加载类的元数据,加载的类越多,需要的内存空间越大,JVM Overhead 则主要用于其他JVM开销,例如代码缓存、线程栈等。
Flink中将内存分成不同的区域,实现了更加精准地内存控制,在使用Flink过程中一般指定Flink总内存(Total Flink Memory,taskmanager.memory.flink.size)即可,其他额外指定JVM内存参数不需额外指定,如果需要根据Flink程序做一些调整建议有限调整fraction比例参数,例如:网络缓存占比taskmanager.memory.network.fraction(根据网络流量大小调节)与托管内存占比taskmanager.memory.managed.fraction(根据RocksDB状态大小调节),这样做可以间接影响任务内存的配额,需要特别注意的是如果手动指定较多的固定参数很有可能出现内存配额冲突导致Flink程序部署失败。
