Spark内存管理
1、介绍
spark内存管理不是通过物理或者硬件底层API实现对内存资源探测,只是通过对内存操作过程期间的字节量的变化不断更新维护的数字,通过该方式跟踪内存使用情况。spark对每个task都关联了内存的使用量,存放在了map<Long,Long>中。严格意义上讲,spark内存的管理是估算量,不是精确量。spark的内存管理主要针对的堆内内存,和离堆非堆无关。
2、Spark内存结构
spark内存是指jvm的堆内存,也称为系统内存。系统内存必须是保留内存的1.5倍以上。由于保留内存默认是300m,因此spark系统内存必须是450m空间以上。
2.1 系统内存设置
-
启动命令设置
$>spark-submit --executor-memory 500m
-
属性配置设置
conf.set("spark.executor.memory" , 500 * 1024 * 1024 + "")
2.2 系统内存结构
系统内存分为如下几个部分:
-
保留内存
硬编码设置空间大小为300m,供spark使用。可以通过如下两个属性关闭或改变大小:
#设置保留内存 $>spark-shell --conf spark.testing.reservedMemory=0 #关闭保留内存 $>spark-shell --conf spark.testing=1
-
可用内存
可用内存空间是系统内存 - 保留内存,内部分为用户内存和spark内存。
-
用户内存
用户内存没有直接设置的参数,是通过给spark内存设置内存比例参数,剩余的就是用户内存。因此
spark.memory.fraction默认是0.6。存储RDD变换的自定义数据结构。
用户内存 = (1 - spark.memory.fraction) * 可用内存
-
spark内存
spark内存占用可用内存的比例是多少通过参数spark.memory.faction(默认0.6)控制。
#设置spark内存占可用内存比例 $>spark-submit --conf spark.memory.faction 0.7 ...
-
存储内存
存储内存通过设置占用spark内存比例完成,属性为spark.memory.storage.faction(默认0.5)。存放缓存数据和串行化数据,以及所有的广播变量也以缓存block方式存放在该区域中。
#设置存储内存占用spark内存比例 $>spark-submit --conf spark.memory.storage.faction 0.6 ...
-
执行内存
执行内存没有指定的参数,确定了存储内存后,剩余的空间就是执行内存。存放task执行期间需要的对象,比如map端shuffle的中间数据buffer,再有就是hash聚合时的hashtable。该部分内存也支持内存不足时spill到磁盘,但是该内存中的block不能被其他线程强制移除。
执行内存 = (1 - spark.memory.storage.faction) * spark内存
-
-
3、内存管理
spark的内存有StaticMemoryManager(静态内存管理)和UnifiedMemoryManager(统一内存管理)。
-
StaticMemoryManager
spark存储内存和执行内存之间不能互相借用,有着严格分界线。是传统模式的内存管理模型。
-
UnifiedMemoryManager
执行内存和存储之间有借用区域,存储内存借用执行内存的时候,如果执行内存不足,可以收回,最多收回借出的部分,不能到对方去抢内存。反之执行内存借用存储内存时,如果存储不足,收不回借出的内存,原因是算法实现比较复杂。