背景
1)java对象的存储密度比较低,对象主要包含 对象头,对象数据,对齐填充。 其中对齐填充是没用的,纯粹是为了让对象的大小到达8的倍数
2)Full GC非常影响性能,对大数据量的计算来说,fullGC可能会持续很久(秒级甚至分钟级)
3)OOM导致JVM崩溃,因为是大数据计算,很有可能会分配出大的对象。
4)缓存未命中,CPU在进行计算时,会先从CPU的缓存中抓取数据,但是jvm堆上的内存不是连续的,会导致CPU缓存不命中,CPU空转,影响效率。
5)传输过程,要序列化和反序列化
解决办法
Flink将对象存储在堆外内存中,或者存在 memorySegment上
memorySegment:
1 翻译为内存段,存储序列化后的对象
2 它是一段固定长度的内存(大小为32KB)
3 是FLink中最小的内存分配单元
4 读写非常高效,很多算子可以直接操作其二进制数据,不需要反序列化
5 Java本身自带的序列化和反序列化的功能,但是辅助信息占用空间比较大,在序列化对象时记录了过多的类信息。
Flink实现了自己的序列化框架,使用TypeInformation表示每种数据类型,所以可以只保存一份对象Schema信息,节省存储空间。又因为对象类型固定,所以可以通过偏移量存取。
JobManager 的内存模型
jobmanager.heap.size:1024m
jobmanager.memory.process.size:1600m
主要包含 堆内存和非堆内存,相对比较简单一些。
TaskManager的内存模型
关于rocksDb内存管理:
由于rocksdb分配的是堆外内存,内存量理论上不受jvm控制。于是产生问题,如果进程的内存使用超过容器限定的量,就会被资源管理器杀死。