分为两种
1.静态内存管理
2.统一内存管理
一.静态内存管理
首先定义内存的大小为3G(--executor-memory 3G)
定义完成后,静态的内存管理,管理的内存分为三大部分
(1)默认占比60%(spark.storage.memoryFraction来配置)
这部分又分成三部分
1.(占10%)为了防止发生OOM预留出来的内存
通过spark.storage.safetyFraction(默认值90%)来配置
2.(占20%)用于数据展开的unroll。RDD数据进行持久化的时候,有可能会选用带有ser的持久化级别。
通过spark.storage.unrollFraction来配置
3.(占70%)存放RDD的缓存数据,广播变量
(2)默认占比20%(通过spark.shuffle.memoryFraction来配置)。这部分的作用是reduce task在计算之前首先获取磁盘小文件的位置,然后通过本进程中的BlockManager启动五个子线程拉取的数据就会存储到这部分内存中。这部分分为两小部分
1.(占80%)用于shuffle
2.(占20%)和上面一样,为了防止发生OOM预留出来的(通过spark.shuffle.safetyFraction配置,默认值0.8)
(3)(默认占20%)用于task的计算,task是一个线程,线程执行需要内存,并且这个线程创建的对象也会存储到这部分内存中。
二.统一的内存管理
比静态的内存管理结构较简单
主要分为三大部分
一.预留出300M给JVM使用
如果本机JVM没有300M内存就会报错
解决方案:手动设置spark.testing.memory配置信息的值,将这个值调小,如果不调整,就默认300M
二.其余内存的75%存放RDD的缓存数据,广播变量,shuffle用的内存(spark.memory.fraction配置)
这部分默认分成两个小部分
1.(默认50%)RDD的缓存数据,广播变量
由spark.memory.storageFraction配置
2.(默认50%)shuffle用的内存
这部分的比例由上一部分的比例决定
在统一的内存管理中Storage内存与shuffle内存可以互相借用,借用的比例不能超过各自的50%。
互相借用这个功能是一个双刃剑,例如,如果是一个IO密集型计算,那么会占用大量的cache内存,就会占用shuffle内存,这样shuffle会非常慢。
三.task执行用的内存。这部分的比例是第二部分的比例决定的