日常工作使用spark处理业务问题中不可避免的都会碰到需要对spark的性能进行调优的情况,这里就介绍一下对spark的性能调优。
1. 调节内存分配
因为在spark中堆内存被划分为两块,一块是给RDD的cache和persist操作RDD数据缓存使用的,另一块是给spark算子函数使用的,函数中自己存放的对象.在默认情况下,分配给cache内存占比为0.6,但是有些cache时候并不需要这么大内存空间,反而task算子中创建的对象有很多,这个时候就会发生spark算子函数使用的空间不够用,而RDD的cache空间有部分是处于一个浪费的状态,这个时候就会导致频繁的full gc,而full gc在执行的时候其他进程是无法执行的,但是spark给我提供一种方法,就是通过修改参数来改变cache的内存分配,可以通过修改cache的内存占比,来给spark算子函数提供更大的内存资源占比。
如果说cache的内存资源不够用,我们可以使用persist将部分RDD缓存数据存到磁盘当中,这样就可以降低gc的频率,从而提高性能我们可以通过 spark.stage.memoryFunction来调节cache的内存占比。
2. 调节executor堆外内存
调节堆外内存,在某些情况下,spark程序处理的数据量非常大,上亿级别的时候,executor的堆外内存可能会存在内存溢出的情况,后续的stage的task运行的时候就会导致程序报错,比如说shuffle output file not found,memory output这样的错误,因为后续的task在运行的时候会从executor中拉去shuffle output file文件,但是这个时候executor已经挂掉了,这样就会导致程序崩溃,任务执行失败。
而在spark中我们可以通过spark.yarn.memeoryOverhead设置参数来调节executor的堆外内存,比如调节为2g,4g,通常这个参数调节后,是可以避免JVM OOM的问题,这样就可以将spark的性能提高。
3. 调节连接时间
Executor首先会从本地的blockmanager中拉取数据,如果本地的block manager中没有数据则会远程连接其他节点上的executor获取数据,但是有的时候task中的对象太大,太多这样就会导致JVM频繁的溢出,而JVM频繁溢出就会发生GC,我们都知道在JVM发生GC的时候,其他的工作线程都是停止的状态,在这个时候需要获取数据的这个executor就无法连接到另一个已经停止的executor,发生这种情况时,也会不断的尝试连接,默认是60秒,如果超过60秒还连接不上,程序就会报错。
在spark中我们可以通过调节spark.core.ack.wait.timeout设置这个连接时间,将时间调节较大之后,通常可以避免偶尔出现的文件拉去不到,文件丢失的一些错误。