Spark内存管理模型
Posted songyuejie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spark内存管理模型相关的知识,希望对你有一定的参考价值。
一般来说,一个spark程序包含两种 JVM 程序,Dirver 和 Executor。Dirver 是主要的控制程序,负责创建 context,提交任务,
那 job 转换为 task 并且协调 task 在 executor 中的执行。Executor 主要是负责执行计算任务并且将结果返回给 Driver。
因为 Driver 的内存管理相对简单,它与普通的 JVM 程序差别并不大。主要关注于 Executor 的内存结构。
堆内(On-Heap) 内存 和 堆外(Off-Heap)内存
Executor 作为一个 JVM 程序,其结构也是基于 JVM的。而 JVM 的内存管理包含两部分:
On-Heap 内存:对象分配基于 JVM 并且会 GC 的控制。
Off-Heap 内存:对象经过序列化后分配在内存外部,由应用程序管理。并且不受 GC 控制。
这一部分的内存结构可以避免频繁的 GC ,但是缺点是必须手动的控制内存的管理和释放逻辑。
一般情况下,对象的读写速度排序是:
on-heap > off-heap > disk
内存分配
在Spark中,支持两种内存管理模式:静态内存管理器和统一内存管理器。
Spark提供了一个统一的接口 MemoryManager 来管理存储和使用内存。同一 executor 中的任务调用该接口以申请或释放内存。
在实现 MemoryManage r时,它默认在Spark 1.6之前使用StaticMemory管理,而默认方法已在Spark 1.6之后更改为 UnifiedMemoryManager。
在Spark 1.6+中,可以通过spark.memory.useLegacyMode参数启用静态内存管理。
静态内存管理器 Static Memory Manager (逐渐被淘汰)
在静态内存管理器机制下,Storage ,EXecution 和其他内存的大小在Spark应用程序运行期间是固定的,但是用户可以在应用程序启动之前对其进行配置。
尽管已逐渐取消了这种分配方法,但出于兼容性原因,Spark仍然保留。
这里主要讨论静态内存管理器的弊端:静态内存管理器机制实现起来比较简单,但是如果用户不熟悉Spark的存储机制,或者不根据特定的数据大小进行相应的配置。
在执行计算任务时,很容易导致其中一个 Storage 内存和 Executor 内存剩余大量空间,而另一个内存首先被填满,因此必须删除旧内容以用于新内容。
统一内存管理器 Unified Memory Manager
Spark 1.6之后引入了统一内存管理器机制。 统一内存管理器和静态内存管理器之间的区别在于,在统一内存管理器机制下,Storage 内存和 Executor 内存共享一个内存区域,
并且两者都可以占据彼此的空闲区域。
On-head model
默认情况下,Spark仅使用堆上内存。 当Spark Application启动时,堆内存由–executor-memory或spark.executor.memory参数配置。 在Executor中运行的并发任务共享JVM的堆上内存。
Executor 中的堆上内存区域可以大致分为以下四个块:
Storage Memory:主要用于存储Spark缓存数据,如RDD缓存,Broadcast变量,Unroll数据等。
Execution Memory:主要用于在Shuffle,Join,Sort,Aggregation等计算过程中存储临时数据。
User Memory:它主要用于存储RDD转换操作所需的数据,例如RDD依赖项的信息。
Reserved Memory:内存是为系统保留的,用于存储Spark的内部对象。
Off-heap model
Spark 1.6开始引入堆外内存(SPARK-11389)。默认情况下,堆外内存是禁用的,但是我们可以通过spark.memory.offHeap.enabled
参数启用它 ,并通过spark.memory.offHeap.size
参数设置内存大小 。
与堆上内存相比,堆外内存的模型相对简单,仅包括 Storage 内存和 Executor 内存,其分布如下图所示:
如果启用了堆外内存,则 Executor 中将同时有堆上内存和堆外内存。此时,Executor 中的 Execution 内存是堆内部的 Execution 内存与堆外部的 Execution 内存之和。Storage 内存也是如此。下图显示了Spark堆内部和外部的堆上和堆外内存。
动态占用机制
- 提交程序后,将根据该
spark.memory.storageFraction
参数设置 Storage 存储区和 Execution 存储区 。 - 当程序运行时,如果双方的空间不足(存储空间不足以放置一个完整的块),它将根据LRU存储到磁盘;如果其中一个空间不足,而另一个空间可用,则它将借用另一个空间。
- Storage 占用对方的内存,然后将占用的部分转移到硬盘上,然后“返还”借来的空间。
- Execution 占用了对方的内存,在当前实现中无法“返还”借用的空间。因为由Shuffle进程生成的文件将在以后使用,并且以后不必再使用Cache中的数据,所以返回内存可能会导致严重的性能下降。
以上是关于Spark内存管理模型的主要内容,如果未能解决你的问题,请参考以下文章
Spark学习之路 SparkCore的调优之Spark内存模型[转]