1.spark内存分配
MemoryManager
|__StaticMemoryManager 静态内存管理机制
|__UnifiedMemoryManger 统一内存管理机制
1.静态内存管理机制
静态内存管理机制实现起来较为简单,但没有根据具体的数据规模和计算任务做相应的配置,很容易造成"一半海水,一半火焰"的局面,即存储内存和执行内存中的一方剩余大量的空间,而另一方却早早被占满,不得不淘汰或移出旧的内容以存储新的内容。由于新的内存管理机制的出现,这种方式目前已经很少有开发者使用,出于兼容旧版本的应用程序的目的,Spark 仍然保留了它的实现。
2.统一内存管理机制
-
统一内存管理机制组成:
-
系统预留内存(System Reserved)
默认300M
-
Storage内存
默认占比:50% 用于缓存RDD(核心),展开partition,存放Direct Task Result、存放广播变量。在Spark Streaming receiver模式中,也用来存放每个batch的blocks。
-
Execution内存
默认占比:50% 用于shuffle、join、sort、aggregation 等操作中的缓存、buffer。 存储内存 + 执行内存 ,统一的受管理器管理, 由UnifiedMemoryManager管理。
-
其他内存
剩余的空间(40%)保留用于用户数据结构,Spark中的内部元数据,并且在稀疏和异常大的记录的情况下保护OOM错误。本块内存,不受MemoryManager管理。 在spark 运行过程中使用: 比如序列化及反序列化使用的内存,各个对象、元数据、临时变量使用的内存,函数调用使用的堆栈等。 作为误差缓冲: 由于storage 和execution 中有很多内存的使用是估算的,存在误差。当storage 或execution 内存使用超出其最大限制时,有这样一个安全的误差缓冲在可以大大减小OOM 的概率。
-
-
内存使用估算:
当spark-submit ... --executor-memory 1g时候
可用内存为:1024m - 300m 300m为系统预留
统一内存为:可用内存 x 60%
storage 和 execution 各占统一内存一半
最终计算结果:
storage: (1024 - 300) * 600 * 0.5 = 217m
execution: (1024 - 300) * 600 * 0.5 = 217m
- 动态占用机制
- 核心店:双向占用,单向清除
1.如果双方空间都占满了,就溢出到磁盘上
2.双向占用,storage和Execution都可以占用对方的空闲空间
3.单向清除,只有Execution可以清除被storage占用的空间,反之 storage不可以清除占用。