一、理论

作为一个JVM 进程,Spark 的内存管理建立在JVM 的内存管理之上,Spark 对JVM的堆内内存基础上进行了更为详细的
分配,以充分利用内存。同时,Spark 引入了堆外内存(Off-heap),可以直接在工作节点的系统内存中开辟空间,进一步 优化了内存的使用。

1.1. 内存模式

1.1.1. 堆内内存(On-heap)

堆内内存的大小,由 Spark 应用程序启动时的 -executor-memoryspark.executor.memory 参数配置。主要包括几个部分:

  1. 存储内存(Storage)
    Executor 内运行的并发任务共享 JVM 堆内内存,这些任务在存储 Shuffle 中间文件、缓存RDD 数据和 Broadcast 数据时占用的内存被规划为存储内存
  2. 执行内存
    任务在执行 Shuffle 时古用的内存被规划为执行内存
  3. reverse
    默认都是 $300$ MB,硬编码到代码中。
  4. 用户内存
    Spark 程序中产生的临时对象实例、Spark 内部的对象实例或者是用户自己维护的一些数据结构也需要给予它一部份的存储空间,可以认为是程序运行时用户可以主导的空间,叫用户操作空间

1.1.2. 堆外内存(Off-heap)

堆外内存的申请和释放不再通过 JVM 机制,而是直接向操作系统申请,减少了不必要的内存开销,以及频繁的 GC 扫描和回收,提升了处理性能。
在默认情况下堆外内存并不启用,可通过配置 spark.memory.offHeap.enabled 参数启用,并由 spark-memory.offHeap.size 参数设定堆外空间的大小。
除了没有 other 空间,堆外内存与堆内内存的划分方式相同,所有运行中的并发任务共享存储内存和执行内存。

1.2. 内存管理

1.2.1. 静态内存管理

在 Spark 最初采用的静态内存管理机制,存储内存、执行内存在 Sperk 应用程序运行期间均为固定的,但用户可以应用程序启动前进行配置。
存储内存和执行内存都有预留空间,防士00M。
静态内存管理机制实现起来较为符单,但不熟悉 Spark 的存储机制,或没有根据具体的数据规模和计算任务或饮相应的配置,容易
造成存储内存和执行内存中的一方剩余夫是的空间,而另一方却早早被占满,不得不海法或移出的内容以存储新的内容—
静态内存管理机制己经废弃台

1.2.2. 统一内存管理

统一内存管理机制最重要的优化在于动态占用机制,其规则如下:

  1. 设定基本的存储内存和执行内存区域 (spark.storage.storageFraction 参数)

  2. 双方的空间都不足时,则存储到硬盘

  3. 若己方空间不足而对方空余时,可借用对方的空间

    存储空间不足是指不足以放下一个完整的 Block, 执行内存的空间被对方占用后,可让对方将占用的部分转存到磁盘,然后归还借用的空间

  4. 存储内存的空间被对方占用后, 无法让对方归还, 因为需要考虑 Shuffle 过程中的很多因素,实现起来较为复杂。

二、实现

2.1. 架构设计

MemoryStore 负责将 Block 存储到内存

2.2. 组件

2.2.1. 内存池

内存池实质上是对物理内存的逻辑规划,协助 Spark 任务在运行时合理地使用内存资源。Spark 将内存从逻辑上区分为堆内存和堆外内存,称为内存模式(MemoryMode)
枚举类型 MemoryMode 中定义了堆内内存和堆外内存

1
2
3
4
public enum MemoryMode {
ON_HEAP,
OFF_HEAP
}

这里的堆內存并不能与 JVM 中的Java 堆直接画等号,只是 JVM 堆内存的一部分。

堆外内存则是 Spark 直接在工作节点的系统内存中开辟的空间。无论是哪种内存,都需要一个内存池对内存进行资源管理,抽象类 MemoryPool 定义了内存池的规范。

  1. 内存池模型

  2. 内存池实现
    Spark 中一共有两种 MemoryPool 的具体实现,Spark 既将内存作为存储体系的一部分,又作为计算引|擎所需要的计算资源,因此MemoryPool既有用于存储体系的实现类 StorageMemoryPool,又有用于计算的 ExecutionMemoryPool。

2.2.2. MemoryManager

抽象类 MemoryManager 定义的内存管理器的接口规范

MemoryManager 子类 UnifiedMemoryManager 提供了统一的内存管理机制,即 Spark 应用程序在运行期的存储內存和执行内存将共享统一的内存空间,可以动态调节两块內存的空间大小

2.2.3. MemoryStore

MemoryStore 相比于MemorManager,提供了一种宏观的内存模型,MemoryManager模型的堆内存和堆外内存在 MemoryStore 的内存模型中是透明的,UnifiedMemoryManager 中存储内存与计算内存的边界在 MemoryStore 的内存模型中也是透明的。