目录
内存管理
Flink是由Java语言所开发的,而基于JVM的数据分析引擎都需要面对将大量的数据存到内存当中,JVM存在以下几个问题:
- Java对象存储密度低。因为Java对象需要存储许多其他信息,比如一个boolean对象就占用了16个字节内存,其中包括了对象头占8个字节,boolean占一个字节,对齐填充占了7个。相当于浪费了15个字节。
- Full GC会极大地影响性能,尤其是为了处理更大数据而开了很大内存空间的JVM,GC有可能会达到秒级甚至是分钟级。
- OOM问题影响稳定性。OOM是分布式计算框架经常遇到的问题,当JVM中所有对象大小超过分配给JVM的内存大小时,就会发生OOM错误,导致JVM崩溃,分布式框架的健壮性和性能都会受到影响。
所以,目前越来越多的大数据项目开始自己管理JVM内存了,为的就是获得像C一样的性能以及避免OOM的发生,不过要注意内存的释放问题。Flink为了解决上面的问题,主要是在内存管理、定制的序列化工具、缓存友好的数据结构和算法、堆外内存、JIT编译优化等进行处理。
积极的内存管理
Flink并不是将大量的对象存在堆上,而是将对象都序列化到一个预分配的内存块上,这个内存块叫做MemorySegment(在反压机制那里提到过),代表了一段固定长度的内存(默认是32KB),也是Flink中最小的内存分配单元,并且提供了非常高效的读写方法。你可以把MemorySegment想象成是为Flink定制的java.nio.ByteBuffer。底层可以是一个普通的Java字节数组(byte[]),也可以是一个申请在堆外的ByteBuffer。每条记录都会以序列化的形式存储在一个或多个MemorySegment中。
Flink在TaskManager运行用户代码的JVM进程。TM的堆内存主要被分成了三个部分。
- Network Buffers:一定数量的MemorySegment,主要用于网络传输。在TaskManager启动时分配,通过NetworkEnvironment和NetworkBufferPool进行管理。
- Managed Memory:由MemoryManager管理的一组MemorySegment集合,主要用于Batch模式下的sorting,hashing和cache等。
- Remaining JVM heap:余下的堆内存留给TaskManager的数