Spark性能调试是使用Spark的用户在进行大数据处理的时候必须面对的问题,性能调优的方法有很多,这里首先介绍一种常见的调优问题-小分区合并问题。

小分区合并问题介绍

在使用Spark进行数据处理的过程中,常常会使用filter方法来对数据进行一些预处理,过滤掉一些不符合条件的数据。在使用该方法对数据进行频繁过滤或者是过滤掉的数据量过大的情况下就会造成大量小分区的生成。在Spark内部会对每一个分区分配一个task执行,如果task过多,那么每个task处理的数据量很小,就会造成线程频繁的在task之间切换,使得资源开销较大,且很多任务等待执行,并行度不高,这会造成集群工作效益低下。
为了解决这一个问题,常采用RDD中重分区的函数(coalesce函数或rePartition函数)来进行数据紧缩,减少分区数量,将小分区合并为大分区,从而提高效率。

实战分析

这里以输入法日志数据为示例数据集进行上述问题分析,对数据进行多次过滤(下图中1所示部分)然后进行相应指标的统计,具体代码如下图:

spark 读取hfile spark 读取小文件合并_性能

提交该任务,Spark运行结果在Web UI界面查看如下:

spark 读取hfile spark 读取小文件合并_spark_02

从图中可以看到,这里总共有两个job,这两个job下面的task数量分别达到6625,26496,且实际上每个任务的数据量也比较小,大概在1M左右,这就是上文所说的小分区过多问题,会一定程度上影响Spark的处理性能,从图中标红的2可以看出,这两个job的执行时间分别为1.2min与3.3min

对上述小分区问题进行合并处理,即采用coalesce函数,将本文第一张图中标红的2部分注释的代码取消注释,设置分区数为120,重新运行结果如下图所示:

spark 读取hfile spark 读取小文件合并_调试_03

从上图可以看出,两个job的运行时间分别缩短至4s和1.5min,且task数量也减少到我们预先设定的分区数量,这里面第二个job中完成task数量是7104的原因是包含了我们没有加入coalesce函数之前处理的任务数量,见下图:

spark 读取hfile spark 读取小文件合并_调试_04

可以看出,在coalesce函数处理过后每个执行过程中task数量已经变为120,符合我们的预期。