大数据开发Flink

大数据开发:Flink内存数据结构

2021-08-03  本文已影响0人  成都加米谷大数据

Flink作为流计算代表性的框架,近几年来的热度越来越高,而Flink流处理,核心思想是有状态的流计算,这就要求在数据存储和管理要能跟得上场景需求,确保高性能,高可靠。今天的大数据开发学习分享,我们来讲讲,Flink内存数据结构。

Flink的内存管理像OS管理内存,划分为段和页。

1、内存段

内存段,即MemorySegment,是Flink内存抽象的最小分配单元。其实就是一个内存块,默认32KB。

MemorySegment可以在堆上:Java byte数组;也可以在堆外:基于Netty的ByteBuffer。

对于Java基本类型,MemorySegment可以直接读写二进制数据,对于其他类型,读取byte[]后反序列化,修改后序列化到MemorySegment。

HeapMemorySegment分配堆上内存,HybridMemorySegment分配堆外内存,实际上后来Flink用HybridMemorySegment分配堆外堆内内存。这设计JIT的编译优化。如果同时使用两个类,运行时每一次都要去查询函数表,确定调用哪个子类中的方法,无法提前优化。如果只是用一个实现子类,自动识别方法的调用都可以被虚化和内联,性能差在2.7倍左右。HybridMemorySegment使用Unsafe提供的一系列方法同时操作堆上和堆外内存。

2、内存页

MemorySegment的抽象粒度面向的是OS的内存管理,这种抽象对于上层的读写显然过于繁琐,Flink又抽象了一层,即内存页。内存页是MemorySegment之上的数据访问视图,数据读取抽象为DataInputView,数据写抽象为DataOutputView。

对于内存的读写是非常底层的行为,对于上层应用(DataStream作业)而言,涉及向MemorySegment写入、读取二进制的地方都使用到了DataInputView、DataOutputView,而不是直接使用MemorySegment。

3、Buffer

Task算子处理完数据后,将结果交给下游的时候,使用的抽象或者说内存对象是Buffer。其实现类是NetworkBuffer。一个NetworkBuffer包装了一个MemorySegment。

NetworkBuffer底层是MemorySegment。Buffer的申请释放由Flink自行管理,Flink引入了引用计数的概念,当有新的Buffer消费者,引用加一,当消费完,引用减1,最终当引用数变为0,就可以将Buffer释放了。

AbstractReferenceCountedByteBuf是Netty中的抽象类。通过实现该类,Flink拥有了引用计数控制Netty申请到的Buffer的内存的能力。

4、Buffer资源池

Buffer资源池:BufferPool,用来管理Buffer,包含Buffer的申请、释放、销毁、可用Buffer的通知。实现类是LocalBufferPool,每个Task拥有自己的LocalBufferPool。

为了方便对BufferPool的管理,设计了BufferPoolFactory,唯一实现类是NetworkBufferPool。每个TaskManager只有一个NetworkBufferPool。同一个TaskManager共享NetworkBufferPool。

关于大数据开发学习,Flink内存数据结构,以上就为大家做了大致的介绍了。Flink内存数据结构,建议要多深入,可以结合到源码去理解。

上一篇下一篇

猜你喜欢

热点阅读