Spark采取基于内存计算的模式,很大程度上来说,对于提升计算效率的效果是显著的,但是同时也带来了对内存管理的更高要求。Spark对内存的管理,有静态和动态之分。今天的大数据开发分享,我们就主要来讲讲,Spark静态内存管理解析。
spark从1.6开始引入了动态内存管理模式,即执行内存和存储内存之间可以互相抢占。spark提供两种内存分配模式:静态内存管理和动态内存管理。
一、内存空间分配
在Spark最初采用的静态内存管理机制下,存储内存、执行内存和其他内存的大小在Spark应用程序运行期间均为固定的,但用户可以应用程序启动前进行配置,堆内内存的分配如下图所示:
默认情况下,spark内存管理采用unified模式,如果要开启静态内存管理模式。将Spark.memory.useLegacyMode参数调为true(默认为false)。
当调整该参数以后,从SparkEnv.scala中可知,如果为true,内存管理调用静态内存类(StaticMemoryManager)。反之,内存管理采用统一内存管理类(UnifiedMemoryManager)。
二、Execution内存
可用的Execution内存
用于shuffle聚合内存,取决于joins,sorts,aggregations等过程中频繁的IO需要的Buffer临时数据存储。
简单来说,spark在shuffle write的过程中,每个executor会将数据写到该executor的物理磁盘上,下一个stage的task会去上一个stage拉取其需要处理的数据,并且是边拉取边进行处理的(和MapReduce的拉取合并数据基本一样),这个时候会用一个aggregate的数据结构,比如hashmap边拉取数据边进行聚合。这部分内存就被称做execution内存。
从getMaxExecutironMemory方法可知,每个executor分配给execution的内存为:Execution Memory=systemMaxMemory*memoryFraction(默认0.2)*safetyFraction(默认0.8),默认为executor最大可用内存*0.16。
Execution内存在运行时会被分配给运行在JVM上的task。这里不同的是,分配给每个task的内存并不是固定的,而是动态的。spark不是一上来就分配固定大小的内存块给task,而是允许一个task占据JVM所有execution内存。
每个JVM上的task可以最多申请至多1/N的execution内存(N为active task的个数,由spark.executor.cores指定)。如果task的申请没有被批准,它会释放一部分内存,并且下次申请的时候,它会申请更小的一部分内存。
预留内存
Spark之所以有一个SafetyFraction这样的参数,是为了避免潜在的OOM。例如,进行计算时,有一个提前未预料到的比较大的数据,会导致计算时间延长甚至OOM,safetyFraction为storage和execution都提供了额外的buffer以防止此类的数据倾斜。这部分内存叫做预留内存。
三、Storage内存
可用的Storage内存
该部分内存用作对RDD的缓存(如调用cache,persist等方法),节点间传输的广播变量。
从StaticMemoryManager的单例对象中可知,最后为每个executor分配到的关于storage的内存:
StorageMemory=systemMaxMemory*storageMemoryFraction(默认0.6)*safetyFraction(默认为0.9)=0.54,
也就是说默认分配executor最大可用内存的*0.54。
预留内存
同Execution内存中的预留部分。
Unroll
unroll是storage中比较特殊的一部分,它默认占据总内存的20%。
BlockManager是spark自己实现的内部分布式文件系统,BlockManager接受数据(可能从本地或者其他结点)的时候是以iterator的形式,并且这些数据有序列化和非序列化的。需要注以下两点:
a)iterator在物理内存上是不连续的,如果后续spark要把数据装载进内存的话,就需要把这些数据放进一个array(物理上连续)。
b)另外,序列化数据需要进行展开,如果直接展开序列化的数据,会造成OOM,所以,BlockManager会逐渐的展开这个iterator,并逐渐检查内存里是否还有足够的空间用来展开数据放进array里。
unroll的优先级还是比较高的,它使用的内存空间可以从storage中借用,如果在storage中没有现存的数据block,它甚至可以占据整个storage空间。如果storage中有数据block,它可以最大dro。
关于大数据开发,Spark静态内存管理解析,以上就为大家做了简单的介绍了。Spark静态内存管理和动态内存管理是息息相关的两个部分,动态内存管理的部分,接下来也会做相应讲解。
网友评论