Spark内存管理 1.1.堆内内存和堆外内存 1.1.1.堆内内存(on-heap) 在JVM堆上分配的内存,在JVM垃圾回收GC范围内 ①:Driver堆内存:通过–driver-memory 或者spark.driver.memory指定,默认大小1G; ②:Executor堆内存:通过–executor-memory 或者spark.executor.memory指定,默认大小1G 在提交一个Spark Application时,Spark集群会启动Driver和Executor两种JVM进程。 Driver为主控进程,负责创建Context,提交Job,并将Job转化成Task,协调Executor间的Task执行 Executor主要负责执行具体的计算任务,将结果返回Driver 1.1.2.堆外内存(off-heap): 在JVM之外分配的内存,不在JVM垃圾回收GC范围内 ①:Driver堆外内存:通过spark.driver.memoryOverhead指定,默认是Driver堆内存的0.1倍,最小是384MB; ②:Executor堆外内存 :通过spark.executor.memoryOverhead指定,默认是Executor堆内存的0.1倍,最小是384MB; 1.1.3.Driver和Executor内存 ①:Driver内存大小:Driver的堆内存 + Driver的堆外内存 ②:Executor内存大小:Executor的堆内存 + Executor的堆外内存
1.2.内存空间分配 1.2.1.静态内存管理–淘汰 在静态内存管理机制下,存储内存,执行内存和其它内存三部分的大小在Spark应用运行期间是固定的,但是用户可以在提交Spark应用之前进行配置。
1.2.2.统一内存管理-1.6之后,更先进 如果开发者不熟悉Spark的存储机制,或没有根据具体的数据规模和计算任务做相应的配置,很容易会造成资源没有得到合理的分配导致Spark任务失败。 所以Spark 1.6之后引入了统一内存管理机制 统一内存管理机制与静态内存管理的区别在于存储和执行内存共享同一块空间,可以动态占用对方的空闲区域。 也就说存储占用多少内存和执行占用多少内存是不固定的,Spark自身可以根据运行的情况动态调整! 1.2.2.1.堆内动态占用
spark.memory.fraction 堆内的存储内存和执行内存总共所占的比例,默认0.6 spark.storage.storageFraction 用于缓存数据的内存比例,默认0.5 1.2.2.2.堆外动态占用
spark.memory.storageFraction Storage内存所占堆外内存的比例,默认为0.5
凭借统一内存管理机制,Spark 在一定程度上提高了堆内和堆外内存资源的利用率,降低了开发者维护 Spark 内存的难度,但并不意味着开发者可以高枕无忧。譬如,所以如果存储内存的空间太大或者说缓存的数据过多,反而会导致频繁的全量垃圾回收GC,降低任务执行时的性能,因为缓存的 RDD 数据通常都是长期驻留内存的
1.3.总结 Spark的内存管理的特点: 1.使用了统一内存管理,可以在运行时根据运行状态实时的动态调整堆内内存和堆外内存中的存储和计算所需内存的占比 2.有个问题:使用了堆内内存受JVM的GC影响! 而堆内内存的大小是堆外内存的10倍,那么如果JVM在进行GC垃圾回收,那么占用绝大部分内存空间的堆内内存将受影响 因为JVM发生full GC的时候会出现短暂暂停,不能工作,那么就会影响到正在运行的Spark任务