- 堆内内存
堆外内存和堆内内存是相对的二个概念,其中堆内内存是我们平常工作中接触比较多的,我们在jvm参数中只要使用-Xms,-Xmx等参数就可以设置堆的大小和最大值,理解jvm的堆还需要知道下面这个公式:
堆内内存 = 新生代+老年代+持久代
- 常见的垃圾回收算法主要有:
引用计数器法(Reference Counting)
标记清除法(Mark-Sweep)
复制算法(Coping)
标记压缩法(Mark-Compact)
分代算法(Generational Collecting)
分区算法(Region)
- 和堆内内存相对应,堆外内存就是把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机),这样做的结果就是能够在一定程度上减少垃圾回收对应用程序造成的影响。
作为JAVA开发者我们经常用java.nio.DirectByteBuffer对象进行堆外内存的管理和使用,它会在对象创建的时候就分配堆外内存。
DirectByteBuffer类是在Java Heap外分配内存,对堆外内存的申请主要是通过成员变量unsafe来操作,下面介绍构造方法
4.使用spark sql调用get_json_object函数后,报如下错误:yarn 容器被kill,导致任务失败,查看日志:Container killed by YARN for exceeding memory limits
分析数据量发现其实并不大,也就几十万。以前上千万的数据量都不需要这么多内存。因此怀疑是get_json_object函数引起的问题。
去掉get_json_object函数,果然任务非常流畅,而且内存调回6G依然是成功的。
spark.yarn.executor.memoryOverhead这个参数是spark excutor的堆外内存,用于 VM overheads, interned strings, other native overheads, etc。猜想get_json_object应该主要是用的堆外内存。
spark.yarn.executor.memoryOverhead默认等于max(executorMemory * 0.10,384M),那么增大executorMemory再多,堆外内存实际增加的也比较少,因此考虑直接增大spark.yarn.executor.memoryOverhead值。
设置spark.yarn.executor.memoryOverhead等于6G,executor-memory减少到4G,经过测试,任务非常稳定的成功。
解决办法:
/opt/software/spark-2.2.0-bin-hadoop2.6/bin/spark-sql \
--master yarn-client \
--driver-memory 2G \
--driver-cores 2 \
--num-executors 4 \
--executor-cores 4 \
--executor-memory 4G \
--conf "spark.yarn.executor.memoryOverhead=4G" \
......