【Spark内存模型】
Spark在一个executor中的内存分为3块:storage内存、execution内存、other内存。
1. storage内存:存储broadcast,cache,persist数据的地方。
2. execution内存:执行内存,join、aggregate、map等shuffle中间结果都缓存在这部分内存中,满了再写入磁盘,能够减少IO。其实map过程也是在这个内存中执行的。
3. other内存:程序代码执行时预留给自己的内存。
其中,execution和storage是Spark的Executor中内存的占用大户,other占用内存相对少很多。
【spark1.6.0之前版本】
spark1.6.0之前版本,execution和storage的内存分配是独立配置的,使用的参数配置分别是:
spark.storage.memoryFraction:storage内存占Executor总内存比例,default 0.6。
spark.shuffle.memoryFraction:execution内存占Executor总内存比例,default 0.2。
spark1.6.0之前版本,上述两块内存是互相隔离的,无法空闲借用。这就导致了Executor的内存利用率不高,而且需要根据Application的具体情况,使用者自己来调节这两个参数优化Spark的内存使用。
【spark1.6.0及之后版本】
spark1.6.0及之后版本,execution内存和storage内存支持合并配置,使用的参数配置分别是:
spark.memory.fraction:“execution内存+storage内存” 占Executor总内存比例,default 0.75。
spark.memory.storageFraction:storage内存 默认 占Executor总内存比例,default 0.5,如果运行时不够用,且execution内存有空闲,可以借用execution内存。
execution内存和storage内存可以相互借用,提高了内存的Spark中内存的使用率,同时也减少了OOM的情况。
【其他】
1.spark.memory.useLegacyMode:默认值是false,也就是使用上述spark1.6.0及之后版本新的内存管理模型,推荐使用。如果非要想用老的spark1.6.0之前版本老的内存管理模型,配置为true。
2.如果发现task由于频繁的gc导致运行缓慢(通过spark web ui可以观察到作业的gc耗时),意味着task执行用户代码的内存,也就是上述other内存不够用,尝试调低execution和storage内存看看。