Flink TM数据传输时的内存分配

简单分析一下,理解其基本设计思想,基于Flink1.10

一、设计思想

1.1 数据DAG图

写数据的类是ResultPartition,读数据的类是InputChannel

1.2 内存分配图

看内存分配机制就好,其它不用管

TM之间:

TM内部:

1.3 NetworkBufferPool

NetworkBufferPool是TM粒度的,一个TM只有一个,不是任务粒度,读数据与写入数据的使用内存,都从其中进行申请,具体流程见上面的图

二、写数据时的内存分配源码分析

可以先看下ResultPartition类的属性

2.1 BufferPool

其中BufferPool的实现类是LocalBufferPool,它是一个内存池,是ResultPartition维度的,即每个ResultPartition都会有一个,创建时从NetworkBufferPool中申请获取内存,其属性如下:

  1. 其中currentPoolSize代表该LocalBufferPool的最大容量,即MemorySegment个数,MemorySegment 的默认大小是 32 K,支持堆内和堆外内存

  2. 当LocalBufferPool需要获取MemorySegment时,会从availableMemorySegments中获取,如果availableMemorySegments中没有,且numberOfRequestedMemorySegments(已申请的segment数)< currentPoolSize,则去NetworkBufferPool中申请,否则返回null,然后阻塞生产者线程

  3. numberOfRequiredMemorySegments和maxNumberOfMemorySegments由TM参数配置

  4. NetworkBufferPool会根据LocalBufferPool的运行情况,根据其numberOfRequiredMemorySegments和maxNumberOfMemorySegments,动态调整LocalBufferPool的currentPoolSize

  5. 具体的数据写入类是ResultSubpartition,当ResultSubpartition需要写入数据时会从ResultPartition中的LocalBufferPool申请新的内存块,并放入自己的buffers中

三、读数据时的内存分配源码分析

读数据如果是本地内存读取,是直接通过方法调用的,把内存块传过去

如果是不同机器间的内存读取,需要从NetworkBufferPool中分配内存

RemoteInputChannel主要负责读取网络间的数据,从网络中收到的数据buffer,会拷贝在bufferQueue中的内存块中,并放在receivedBuffers中

bufferQueue代表的是可用内存,主要用于把通过网络传输收到的数据buffer的内容拷贝其中

bufferQueue包括独占内存和浮动内存,RemoteInputChannel初始化时,独占内存会从NetworkBufferPool中申请,数量为numberOfSegmentsToRequest,默认为2

浮动内存是当bufferQueue中内存不够用时,小于 初始可用内存+生产者没法送的内存,就会从InputGate中去申请

InputGate会从自己的bufferPool中去拿,bufferPool如果不够,会去NetworkBufferPool中申请

四、为什么要使用内存池

直接采用纳米ai的回答吧:

假设LocalBufferPool 是一个内存池,存储了100个MemorySegment,MemorySegment代表32kb内存,LocalBufferPool 用于数据传输

使用了内存池:

假设任务A需要将一批数据通过网络发送给任务B,流程如下:

  1. 申请内存段 :任务A从LocalBufferPool申请5个MemorySegment(共160KB),用于暂存待发送的数据。
  2. 数据填充 :将待传输的数据序列化后,按顺序写入这5个MemorySegment中。
  3. 数据传输 :将填充好的MemorySegment通过网络层直接传输给任务B,避免数据拷贝(如Flink的NetworkBuffer机制1)。
  4. 接收与处理 :任务B从自己的LocalBufferPool中获取空闲的MemorySegment接收数据,反序列化后处理。
  5. 释放内存 :任务A和任务B在处理完成后,将MemorySegment归还到各自的LocalBufferPool中,供后续请求复用。

不使用内存池:

  1. 频繁申请内存 :每次传输数据时,任务A需通过new byte[32*1024]创建多个32KB的字节数组。
  2. 数据拷贝开销:网络传输前需将数据拷贝到临时字节数组,接收方同样需要多次分配临时存储空间。
  3. 依赖GC回收:传输完成后,这些临时数组成为垃圾对象,需等待JVM垃圾回收器(尤其是Full GC)回收,导致不可预测的延迟。
  4. 内存碎片风险 :大量小对象频繁分配/释放易造成堆内存碎片,降低后续内存分配效率24
相关推荐
青鱼入云2 小时前
【面试场景题】电商订单系统分库分表方案设计
大数据·面试·职场和发展
在未来等你3 小时前
Kafka面试精讲 Day 12:副本同步与数据一致性
大数据·分布式·面试·kafka·消息队列
云边云科技3 小时前
门店网络重构:告别“打补丁”,用“云网融合”重塑数字竞争力!
大数据·人工智能·安全·智能路由器·零售
渣渣盟4 小时前
Spark核心:单跳转换率计算全解析
大数据·spark·scala·apache
edisao5 小时前
[特殊字符] 从助手到引擎:基于 GPT 的战略协作系统演示
大数据·人工智能·gpt
IT毕设梦工厂5 小时前
大数据毕业设计选题推荐-基于大数据的国家医用消耗选品采集数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
大数据·hadoop·信息可视化·spark·毕业设计·数据可视化·bigdata
华略创新6 小时前
利用数据分析提升管理决策水平
大数据·数据分析·crm·管理系统·软件
pingao1413786 小时前
PG-210-HI 山洪预警系统呼叫端:筑牢山区应急预警 “安全防线”
大数据·人工智能·科技
庄小焱7 小时前
大数据存储域——Kafka设计原理
大数据·kafka·消息中间件
Elastic 中国社区官方博客7 小时前
带地图的 RAG:多模态 + 地理空间 在 Elasticsearch 中
大数据·人工智能·elasticsearch·搜索引擎·ai·语言模型·全文检索