Spark发生垃圾回收的原理:
GC:garbage collector 垃圾回收
executor是JVM中的服务进程。Spark任务运行的时候就是不断的在executor中创建对象。若JVM存不下对象了,就会触发GC(把不需要的对象清除)。
若内存中数据量较大,则可能会很频繁的发生GC,而GC本身很耗费性能,对Spark作业性能影响很大。
同时若数据量很大,那么GC一个涉及的数据量也很大,同样导致GC速度较慢。
除此之外,GC的时候是一条线程,GC运行的时候,会让Spark作业运行时候的那些工作线程停止让GC进程单独运行。会导致Spark作业性能影响较大。
垃圾回收过程
executor分为两部分老年代、新生代。
1. 新生代分为:Eden区、survivor1、survivor2
运行Spark任务会不断产生创建对象,对象会首先进入Eden区,Eden区存满,对象会进入survivor1区;若survivor1区也存满。就会发生minor GC。会在新生代中把不需要使用的对象进行回收。
2. 把还存活的、没被回收掉的对象放入survivor2区。之后,survivor1已经清空,接着survivor1和survivor2进行调换。
3. 若survivor2也不够用时,会把对象存入老年代中。(如果一个对象在新生代多次发生minor GC,还是没被回收,说明它是长时间存活的对象,就会把这些对象移到老年代中)
4. 若一直这么移动,老年代也存满,就会触发full GC(非常耗费资源)
不正常情况:若Eden区不够大,很可能出现大量的数据频繁进入survivor区,那么会频繁的进入老年代,full GC就会频繁的发生,会导致工作线程停止,直接印象spark作业运行。
JVM调优
发生full GC根本原因是内存不够用
垃圾回收的性能开销,是跟内存中的对象的数量,成正比的。
1)对于垃圾回收的性能问题,首先要做的就是,使用更高效的数据结构,比如array和string;
2)持久化rdd时,使用序列化的持久化级别,而且用Kryo序列化类库,这样,每个partition就只是一个对象——一个字节数组。
3)给Eden区域分配更大的空间,使用-Xmn即可,通常建议给Eden区域,预计大小的4/3;
如果使用的是HDFS文件,那么很好估计Eden区域大小,如果每个executor有4个task,然后每个hdfs压缩块解压缩后大小是3倍,此外每个hdfs块的大小是64M,那么Eden区域的预计大小就是:4 * 3 * 64MB,然后呢,再通过-Xmn参数,将Eden区域大小设置为4 * 3 * 64 * 4/3。
在使用大数据工具的时候,我们通常使用如下的工具:
Hadoop:HDFS (Namenode、Datanode)、YARN(ResourceManager、NodeManager)
Hbase:Hmaster、 HRegionserver
Spark : Master、 worker
全都是JVM进程(java虚拟机服务进程)
JVM体系: