168大数据

标题: 必须要懂的Spark内存管理模型 [打印本页]

作者: 168主编    时间: 2019-8-20 15:20
标题: 必须要懂的Spark内存管理模型
0、前 言
Apache Spark是目前大数据领域主流的内存计算引擎,无论是在批处理还是实时流处理方面都有着广泛的应用。我们跑作业的时候,首先要给Spark Job分配一定的资源,比如一个executor分配5G内存,有时候我们会纠结于executor的内存有多少用于了实际计算。因此就需要了解一下Spark的内存管理,还有就是掌握了Spark的内存模型对于优化我们的作业也至关重要。
在Spark 1.5及之前版本中,内存管理默认实现是StaticMemoryManager,称为静态内存管理。从Spark 1.6.0版本开始,Spark默认采用一种新的内存管理模型UnifiedMemoryManager,称为统一内存管理,其特点是可以动态调整Execution和Storage的内存,参见SPARK-10000,因此又称为动态内存管理。本文我们就以Executor为例,介绍一下Spark的统一内存管理。

1、Spark内存管理
首先我们看一下Spark的内存使用,主要分为两类:Execution Memory和Storage Memory。其中,Execution Memory主要用于计算,如shuffles、joins、sorts及aggregations等操作,Storage Memory主要用于cache数据和在集群内部传输数据。
Executor默认只使用堆内内存(On-heap Memory)。为了进一步优化内存的使用,Spark引入了堆外内存(Off-heap Memory),默认是关闭状态。接下来,将详细说明Spark Executor堆内内存与堆外内存的具体情况。

1.1 On-heap Memory
Spark Executor通过spark.executor.memory或--executor-memory配置的内存为堆内内存,可以分为以下四块区域:

各个区域内存情况,如下图所示:

以上图解中,参数说明如下:



1.2 Off-heap Memory

为了进一步优化内存的使用,减小GC开销,Spark 1.6版本还增加了对Off-heap Memory的支持,参见SPARK-11389,但Off-heap Memory默认是关闭的,开启须设置参数spark.memory.offHeap.enabled为true,并通过参数spark.memory.offHeap.size设置堆外内存大小,单位为字节。

堆外内存划分上没有了用户内存与预留内存,只包含Execution Memory和Storage Memory两块区域,内存情况如下图所示:


以上图解中,maxOffHeapMemory大小就是spark.memory.offHeap.size的值,spark.memory.storageFraction默认值不变。

3、动态内存分配

在如上两个图解中,我们可以看到Execution Memory与Storage Memory之间有一条可以上下移动的虚线,说明Execution Memory与Storage Memory不是固定不变的,彼此之间可以相互共享,这便是Spark动态内存管理的含义。Spark 1.5及之前版本,两者是固定不变的,即前文提及的静态内存管理。

意思是说,当Execution Memory有空闲,Storage Memory不足时,Storage Memory可以借用Execution Memory,反之亦然。Execution Memory可以让Storage Memory写到磁盘,收回被占用的空间。如果Storage Memory被Execution Memory借用,因为实现上的复杂度,却收回不了空间。

4、Legacy Mode

Spark 1.6版本开始,默认使用动态(统一)内存管理模型,但之前的静态内存管理模型(StaticMemoryManager)仍然保留,通过称为Legacy模式的参数spark.memory.useLegacyMode控制,默认false为不开启静态内存管理。

5、总 结
Apache Spark从1.6.0版本开始,其内存管理模块默认采用了动态内存管理模型,一直延续使用到Spark 2.x。本文参考了社区的一些分享,结合相关图解,从Spark总体内存使用、堆内内存、堆外内存等几个方面,重点对Spark的动态内存管理这块做了简单介绍。

作者:Andy
​来源:大数据手稿笔记






欢迎光临 168大数据 (http://www.bi168.cn/) Powered by Discuz! X3.2