版权声明:尊重原创,转载请标明"本文转自:https://blog.csdn.net/high2011" https://blog.csdn.net/high2011/article/details/84575442
前言
Spark 的内存管理是内存分布式引擎中的一个重要角色,了解内存管理机制和原理,才能更好地做优化。
内容
1、静态内存管理(Spark 1.6.x版本前的策略)
静态内存管理图示——堆内
Unroll 的源码参考:https://github.com/apache/spark/blob/branch-1.6/core/src/main/scala/org/apache/spark/storage/MemoryStore.scala#L249
静态内存管理图示——堆外
2、统一内存管理(Spark 1.6.x以后的策略)
统一内存管理图示——堆内
统一内存管理图示——堆外
其中最重要的优化在于动态占用机制,其规则如下:
1\设定基本的存储内存和执行内存区域(spark.storage.storageFraction 参数),该设定确定了双方各自拥有的空间的范围
双方的空间都不足时,则存储到硬盘;若己方空间不足而对方空余时,可借用对方的空间;(存储空间不足是指不足以放下一个完整的 Block)
2\执行内存的空间被对方占用后,可让对方将占用的部分转存到硬盘,然后"归还"借用的空间
3\存储内存的空间被对方占用后,无法让对方"归还",因为需要考虑 Shuffle 过程中的很多因素,实现起来较为复杂
动态占用机制图示
凭借统一内存管理机制,Spark 在一定程度上提高了堆内和堆外内存资源的利用率,降低了开发者维护 Spark 内存的难度,但并不意味着开发者可以高枕无忧。譬如,所以如果存储内存的 空间太大 或者说 缓存的数据 过多,反而会导致频繁的全量垃圾回收,降低任务执行时的性能,因为缓存的 RDD 数据通常都是长期驻留内存的。所以要想充分发挥 Spark 的性能,需要开发者进一步了解存储内存和执行内存各自的管理方式和实现原理。
统一内存管理还可以简化如图
(1)Reserved Memory
- 不推荐改变此参数(默认即可);
- 系统保留的内存,从Spark 1.6.0开始,它的值为300MB,如果没有Spark重新编译或设置 spark.testing.reservedMemory,它的大小不能以任何方式改变,,因为它不是用于生产的测试参数。
- 如果没有给Spark执行程序至少 1.5 保留内存 = 450MB heap,spark-submit 将失败并显示**“please use larger heap size”*** 的错误消息。
(2)User Memory
- 在分配 Spark Memory之后剩余的内存池;
- 用户可以在那里存储将在RDD转换中使用的数据结构、Spark的元数据,所以必须在编码中注意数据结构的定义和使用;
- 内存池的大小可以计算为(“ Java heap ” - “reserved memory ”)(1.0 - spark.memory.fraction),默认情况下等于(“ Java堆 ” - 300MB ) 0.25
(3)Spark Memory
- Apache Spark管理的内存池;
- 计算:(“ Java堆 ” - “保留内存 ”)* spark.memory.fraction,并且使用Spark 1.6.0默认值它给我们(“ Java堆 ” - 300MB)* 0.75。
Execution Memory 和 Storage Memory 的边界由 spark.memory.storageFraction 设置 参数,默认为0.5。 - Storage Memory:这个内存用于缓存以后还会用到的数据:如广播变量 、persist
- Execution Memory:这个内存用于存储执行Spark shuffles、joins、sorts和aggregations 期间所需的对象。
3、静态内存管理和统一内存管理的区别
静态内存管理 | 统一内存管理 | |
---|---|---|
不同点 | 每个区域都有预留内存,通过参数控制占比 | 只有一个预留内存区域,且该区域是单独的 |
相同点 | 分为三个区域(Storage、Execution和 Other)+ 保留内存 | 分为3个区域(Spark Memory(包含 Storage 和 Execution)、User Memory(Other))+保留内存 |
4、Spark 大部分版本的内存参数整理
选项 | spark 1.6.x之前版本 | spark 1.6.x | spark 2.1.x | spark 2.2.x | spark 2.3.x | spark 2.4.x | 备注 |
---|---|---|---|---|---|---|---|
spark.memory.fraction | 无值 | 0.75 | 0.6 | 0.6 | 0.6 | 0.6 | |
spark.memory.storageFraction | 无值 | 0.5 | 0.5 | 0.5 | 0.5 | 0.5 | |
spark.memory.offHeap.enabled | 无值 | false | false | false | false | false | |
spark.memory.offHeap.size | 无值 | 0 | 0 | 0 | 0 | 0 | |
spark.memory.useLegacyMode | 无值 | false | false | false | false | false | |
spark.shuffle.memoryFraction | 0.2 | 0.2 | 0.2 | 0.2 | 0.2 | 0.2 | |
spark.storage.memoryFraction | 0.6 | 0.6 | 0.6 | 0.6 | 0.6 | 0.6 | |
spark.storage.unrollFraction | 0.2 | 0.2 | 0.6 | 0.2 | 0.2 | 0.2 | |
spark.storage.replication.proactive | 无值 | 无值 | 无值 | false | false | false | |
spark.cleaner.periodicGC.interval | 无值 | 无值 | 无值 | 无值 | 30min | 30min | |
spark.cleaner.referenceTracking | 无值 | 无值 | 无值 | 无值 | true | true | |
spark.cleaner.referenceTracking.blocking | 无值 | 无值 | 无值 | 无值 | true | true | |
spark.cleaner.referenceTracking.blocking.shuffle | 无值 | 无值 | 无值 | 无值 | false | false | |
spark.cleaner.referenceTracking.cleanCheckpoints | 无值 | 无值 | 无值 | 无值 | false | false |
说明
-
1、Spark 内存:本文中均指 Executor 内存
-
2、本文中的分析是基于 Spark v1.6.x 版本
-
3、以上内容是整合参考中的文章后,结合自己的理解而编写,难免有叙述不周之处,如有发现,多多包涵、还请赐教。
参考
- https://spark.apache.org/docs/1.6.3/configuration.html#memory-management
- https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html
- https://0x0fff.com/spark-memory-management/
- https://databricks.com/session/deep-dive-apache-spark-memory-management
- https://blog.csdn.net/u012102306/article/details/51637366
- http://www.importnew.com/26541.html