Spark的统一内存管理机制通过动态分配内存资源来优化计算效率。其核心设计将堆内存划分为统一的内存池,主要包含以下部分:
根据Spark 统一内存管理机制,堆内存被划分为了两块,Storage 和Execution。Storage 主要用于缓存数据,Execution 主要用于缓存在shuffle 过程中产生的中间数据,两者所组成的内存部分称为统一内存,Storage 和Execution 各占统一内存的50%,由于动态占用机制的实现,shuffle 过程需要的内存过大时,会自动占用Storage 的内存区域,因此无需手动进行调节。
一、内存区域划分
存储内存(Storage Memory)
用于缓存RDD、广播变量等数据,占比由参数spark.memory.storageFraction控制(默认0.6)。公式表达:
$$\text{存储内存上限} = \text{堆内存} \times s \quad (s \in [0.5, 0.9])$$执行内存(Execution Memory)
用于Shuffle、Join、聚合等计算过程的临时数据,与存储内存共享剩余空间。
二、动态调整机制
借用规则
- 执行内存不足时可借用空闲的存储内存
- 存储内存不足时可反向借用,但需归还借用的执行内存
$$ \text{可用内存} = \begin{cases} M_{\text{执行}} + (M_{\text{存储空闲}} - M_{\text{借出}}) & \text{执行侧不足} \ M_{\text{存储}} + (M_{\text{执行空闲}} - M_{\text{借出}}) & \text{存储侧不足} \end{cases} $$
驱逐机制
当存储内存被借用且原数据需恢复时,Spark会按LRU策略将部分RDD块溢出到磁盘。
三、溢出处理
当内存不足时,系统自动触发溢出操作:
if (内存压力 > 阈值) { 将Shuffle数据写入磁盘 清除最近未使用的RDD分区 }四、优势与监控
优势
- 避免静态分区导致的内存浪费
- 根据任务需求实时调整资源
监控方式
通过Spark UI的Storage和Executors页签查看内存使用明细。
提示:合理设置
spark.memory.fraction(默认0.6)和spark.memory.storageFraction可优化性能,需结合具体作业特性调整。