Flink新内存模型
将Flink从1.7.2升级到1.10.0时出现各种内存溢出问题,Flink1.10提出了全新的内存模型,使用新版Flink理解新的内存模型是必须。对于老的flink我们一般只需配置taskmanager.heap.size,对于standalone cluster来说这个配置只配置了堆内存,而堆外内存在taskmanager.sh中被配成了一个相当大的数。
TM_MAX_OFFHEAP_SIZE="8388607T"
export JVM_ARGS="${JVM_ARGS} -Xms${TM_HEAP_SIZE}M -Xmx${TM_HEAP_SIZE}M -XX:MaxDirectMemorySize=${TM_MAX_OFFHEAP_SIZE}"
而对于yarn cluster来说这个配置项代表的又是整个container的内存。因此,整理并提出一个新的内存规范的确是有必要的。
TaskManager
TaskManager总内存有2种配置方式total process memory和total flink memory,其中total process memory = total flink memory + jvm运行自身占用内存,例如metaspace。其中total process memory适合在容器环境下使用,对应配置项为taskmanager.memory.process.size,而total flink memory适合在standalone下使用,对应配置项为taskmanager.memory.flink.size。
total flink memory = heap + off-heap。heap被称为堆内存,而off-heap在这里指不是堆内存的内存,这里不称为堆外或者非堆,是为了和这些模糊的概念划清界限。
heap = task heap + framework heap,即用户代码使用的堆内存和flink框架本身使用的堆内存。这部分内存对应的jvm参数最终为-Xmx和-Xms,因此实际上task heap和framework heap是没有隔离的。
off-heap=managed memory + direct memory。managed memory是由Flink用Unsafe类创建的,不受JVM管控。流job中这部分内存可用于状态后端,例如rocksdb的内存;批job这部分内存可用于排序,缓存中间结果等。managed memory也就是slot均分的那个内存(slot的内存隔离其实只有这一部分而已),因此是按slot隔离的。direct memory就是我们平常所说的堆外内存:java.nio.DirectByteBuffer,这部分内存也由Unsafe类创建的,照理也不受JVM控制,但是在JDK代码里使用了-XX:MaxDirectMemorySize对其进行了大小上的管控。java.nio.Bits#tryReserveMemory中限制了大小。direct memory对应的JVM参数为-XX:MaxDirectMemorySize。
private static boolean tryReserveMemory(long size, int cap) {
// -XX:MaxDirectMemorySize limits the total capacity rather than the
// actual memory usage, which will differ when buffers are page
// aligned.
long totalCap;
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
reservedMemory.addAndGet(size);
count.incrementAndGet();
return true;
}
}
return false;
}
direct memory = framework off-heap + task off-heap+ network。其中network会在初始化时分配,可以视为和前2部分是隔离的,而前2部分之间是没有隔离的。
taskmanager.memory.jvm-metaspace.size是用来设置metaspace的,对应的JVM参数是-XX:MaxMetaspaceSize。Flink1.10新增了cluster.evenly-spread-out-slots配置,开启后job的slot会在TaskManager上均分,对于standalone cluster来说每个TaskManager需要加载的job就会变多,类加载变多需要更大的metaspace空间。 TaskManager内存模型如下图:
JobManager
Flink1.11又提出了新的JobManager内存模型来规范JobManager的设置。JobManager的内存设置相对于TaskManager简单的多,在理解了TaskManager内存模型后在看JobManager的内存模型就简单的多了。
JobManager内存模型如下图: