Spark内存模型在1.6版本之前版本采用的是静态管理(Static Memory Manager)的方式,在1.6之后采用的是统一管理(Unified Memory Manager)的方式。且Spark的可用内存分为堆内和堆外,所以本文先对静态内存管理的机制进行讲解。
一、堆内
静态管理(堆内)的模型如下图所示:
静态内存管理中,内存主要规划为3部分:
一、Storage:
1、该区域的作用有:
(1)存储缓存的RDD
(2)存储广播数据
(3)保存Spark在处理过程中产生的数据
2、预留区的说明:
(1)前提说明:RDD缓存中是可以指定数据是否序列化的。如果数据不是序列化的,那么是采用估值的方式来计算占用内存的大小;如果数据时序列化的,那么数据是按照二进制字节流存储的,那么就可以精准统计出占用的内存情况。此外,在被 Spark 标记为释放的对象实例,很有可能在实际上并没有被 JVM 回收,导致实际可用的内存小于 Spark 记录的可用内存。
(2)说明:预留区就是为了减少 因存储非序列化数据导致的内存占用估值差错而导致的OOM 的情况
3、Unroll区域说明:
(1) 概念:将Partition由不连续的存储空间转换为连续存储空间的过程,Spark称之为”展开”(Unroll)
(2) 作用:以RDD缓存来说明的话,就是将在Other区中不连续的RDD数据写到unroll区,使之成为连续的区域。
二、 Execution:
1、作用:在执行 Shuffle 时占用的内存被规划为执行(Execution)内存
2、预留区的作用:和Storage的预留区是一言的
三、 Other:
1、作用:Spark 内部的对象实例,或者用户定义的 Spark 应用程序中的对象实例占用的内存区域
二、堆外
静态管理(堆外)的模型如下图所示:
堆外内存分为存储内存(Storage)和执行内存(Execution),作用和堆内的是一致的,所以这里不再多阐述。
三、弊端
虽然静态内存管理的方式比较简单,但是如果没有根据自己数据处理的情况对上面参数进行配置的话,很容易造成“一半火焰、一半海水”的情况,即存储内存和执行内存中的一方剩余大量的空间,而另一方却早早被占满,不得不淘汰或移出旧的内容以存储新的内容。
所以才会出现Spark 1.6以后的统一内存管理模型。但是出于对旧版本的兼容,Spark还保留着这种模型。
注:本文的内容和图片摘取于:https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html