Flink内存模型图
JVM Heap
JVM Heap的划分
JVM ONHEAP
- JVM内存划分为堆内存和非堆内存,堆内存分为年轻代(Young Generation)、老年代(Old Generation),非堆内存就一个永久代(Permanent Generation)。
- 年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1。实际上是6:1:1
- 堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。
- 非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。
JVM OFFHEAP
**堆外内存**就是把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接**受操作系统管理**(而不是虚拟机),这样做的结果就是**能够在一定程度上减少垃圾回收对应用程序造成的影响。**
堆外内存存放:所有线程共享的方法区,方法区中包含类结构、常数池、字段和方法数据,以及方法和构造方法的代码
Flink FrameworkHeap 存放了什么?
存放了Flink框架所需要用到的对象
Task Heap 存放了什么?
存放了Task中创建的对象
Off-Heap Memory
堆外内存的好处与劣势
好处:jvm虚拟化大量heap内存耗时较久,使用堆外内存的话可以有效的避免该环节
坏处:监控调试使用相对复杂,对于生命周期较短的segment使用堆内内存开销更低,flink在一些情况下,直接操作二进制数据,避免一些反序列化带来的开销。如果需要处理的数据超出了内存限制,则会将部分数据存储到硬盘上。
Managed Memory
存储:
RocksDBStateBackend
批处理算子,排序、哈希表、缓存中间结果
属于native memory的范畴
RocksDBStateBackend:
即Rocksdb,rocksdb基于lsm数据结构实现,每个state对应一个列族。
占有独立的writebuffer,rocksdb占用native内存大小为 blockCahe + writebufferNum * writeBuffer + index 。
同时堆外内存是进程之间共享的
Direct Memory 直接内存
什么是直接内存?
直接内存实质上是堆外内存native memory通过存储在堆内的**DirectByteBuffer**操作native memory
什么时候使用直接内存?
如果读写频繁的操作可以使用直接内存,直接内存的速度会优于java堆,可以使用java Nio库,用于数据缓冲
图解直接缓冲区
非直接缓冲区:
直接缓冲区:
应用程序直接内核态访问,节省copy
存在的隐患
OOM,直接内存+JVM堆内存会受操作系统的限制
分配回收成本较高,不受JVM内存回收管理
分配
- 直接内存大小可以通过MaxDirectMemorySize设置
- 如果不指定,默认与堆的最大值一Xmx参数值一致
Network
关于Network对堆外内存的使用可以查看反压机制