佛山论坛建站模板,网站 建设设计,黄骅港在哪里,设计师导航2019独角兽企业重金招聘Python工程师标准 Spark 作为一个以擅长内存计算为优势的计算引擎#xff0c;内存管理方案是其非常重要的模块#xff1b; Spark的内存可以大体归为两类#xff1a;execution和storage#xff0c;前者包括shuffles、joins、sorts和agg… 2019独角兽企业重金招聘Python工程师标准 Spark 作为一个以擅长内存计算为优势的计算引擎内存管理方案是其非常重要的模块 Spark的内存可以大体归为两类execution和storage前者包括shuffles、joins、sorts和aggregations所需内存后者包括cache和节点间数据传输所需内存在Spark 1.5和之前版本里两者是静态配置的不支持借用spark1.6 对内存管理模块进行了优化通过内存空间的融合消除以上限制提供更好的性能。官方网站只是要求内存在8GB之上即可Impala推荐要求机器配置在128GB 但spark job运行效率主要取决于数据量大小内存消耗内核数确定并发运行的task数量 目录 基础知识spark1.5- 内存管理spark1.6 内存管理基本知识 on-heap memoryJava中分配的非空对象都是由Java虚拟机的垃圾收集器管理的也称为堆内内存。虚拟机会定期对垃圾内存进行回收在某些特定的时间点它会进行一次彻底的回收full gc。彻底回收时垃圾收集器会对所有分配的堆内内存进行完整的扫描这意味着一个重要的事实——这样一次垃圾收集对Java应用造成的影响跟堆的大小是成正比的。过大的堆会影响Java应用的性能off-heap memory堆外内存意味着把内存对象分配在Java虚拟机的堆以外的内存这些内存直接受操作系统管理而不是虚拟机。这样做的结果就是能保持一个较小的堆以减少垃圾收集对应用的影响LRU CacheLeast Recently UsedLRU可以说是一种算法也可以算是一种原则用来判断如何从Cache中清除对象而LRU就是“近期最少使用”原则当Cache溢出时最近最少使用的对象将被从Cache中清除spark 源码 https://github.com/apache/spark/releasesscale ide for Intellij : http://plugins.jetbrains.com/plugin/?id1347Spark1.5- 内存管理 1.6 版本引入了新的内存管理方案配置参数 spark.memory.useLegacyMode 默认 false 表示使用新方案true 表示使用旧方案 SparkEnv.scala 源码 如下图 在staticMemoryManager.scala 类中查看构造类及内存获取定义 通过代码推断若设置了 spark.testing.memory 则以该配置的值作为 systemMaxMemory否则使用 JVM 最大内存作为 systemMaxMemory。spark.testing.memory 仅用于测试一般不设置所以这里我们认为 systemMaxMemory 的值就是 executor 的最大可用内存Execution用于缓存shuffle、join、sort和aggregation的临时数据通过spark.shuffle.memoryFraction配置spark.shuffle.memoryFractionshuffle 期间占 executor 运行时内存的百分比用小数表示。在任何时候用于 shuffle 的内存总 size 不得超过这个限制超出部分会 spill 到磁盘。如果经常 spill考虑调大参数值spark.shuffle.safetyFraction为防止 OOM不能把 systemMaxMemory * spark.shuffle.memoryFraction 全用了需要有个安全百分比最终用于 execution 的内存量为executor 最大可用内存* spark.shuffle.memoryFraction*spark.shuffle.safetyFraction默认为 executor 最大可用内存 * 0.16execution内存被分配给JVM里的多个task线程。task间的execution内存分配是动态的如果没有其他tasks存在Spark允许一个task占用所有可用execution内存storage内存分配分析过程与 Execution 一致由上面的代码得出用于storage 的内存量为: executor 最大可用内存 * spark.storage.memoryFraction * spark.storage.safetyFraction默认为 executor 最大可用内存 * 0.54在 storage 中有一部分内存是给 unroll 使用的unroll 即反序列化 block该部分占比由 spark.storage.unrollFraction 控制默认为0.2通过代码分析storage 和 execution 总共使用了 80% 的内存剩余 20% 内存被系统保留了用来存储运行中产生的对象,该类型内存不可控.小结 这种内存管理方式的缺陷即 execution 和 storage 内存表态分配即使在一方内存不够用而另一方内存空闲的情况下也不能共享造成内存浪费为解决这一问题spark1.6 启用新的内存管理方案UnifiedMemoryManagerstaticMemoryManager- jvm 堆内存分配图如下 Spark1.6 内存管理 从spark1.6开始引入了新的内存管理方式-----统一内存管理(UnifiedMemoryManager)在统一内存管理下spark一个executor中的jvm heap内存被划分成如下图: Reserved Memory,这一部分的内存是我们无法使用的部分spark内部保留内存会存储一些spark的内部对象等内容。spark1.6默认的Reserved Memory大小是300MB。这部分大小是不允许我们使用者改变的。简单点说就是我们在为executor申请内存后有300MB是我们无法使用的。并且如果我们申请的executor的大小小于1.5 * Reserved Memory 即 450MBspark会报错:User Memory用户在程序中创建的对象存储等一系列非spark管理的内存开销都占用这一部分内存Spark Memory该部分大小为 (JVM Heap Size - Reserved Memory) * spark.memory.fraction,其中的spark.memory.fraction可以是我们配置的(默认0.75)如下图如果spark.memory.fraction配小了我们的spark task在执行时产生数据时包括我们在做cache时就很可能出现经常因为这部分内存不足的情况而产生spill到disk的情况影响效率。采用官方推荐默认配置Spark Memory这一块有被分成了两个部分Execution Memory 和 Storage Memory,这通过spark.memory.storageFraction来配置两块各占的大小(默认0.5一边一半)如图Storage Memory主要用来存储我们cache的数据和临时空间序列化时unroll的数据以及broadcast变量cache级别存储的内容Execution Memory则是spark Task执行时使用的内存(比如shuffle时排序就需要大量的内存)为了提高内存利用率spark针对Storage Memory 和 Execution Memory有如下策略: 一方空闲一方内存不足情况下内存不足一方可以向空闲一方借用内存只有Execution Memory可以强制拿回Storage Memory在Execution Memory空闲时借用的Execution Memory的部分内存如果因强制取回而Storage Memory数据丢失重新计算即可如果Storage Memory只能等待Execution Memory主动释放占用的Storage Memory空闲时的内存。(这里不强制取回因为如果task执行数据丢失就会导致task 失败) 转载于:https://my.oschina.net/hblt147/blog/1571528