【Spark性能调优】长尾任务如何优化
背景
Spark 长尾任务是指在 Spark 作业中,大部分任务都很快完成,但少数任务运行时间非常长,拖慢了整个作业的执行速度。 这些长尾任务就像一条长长的“尾巴”,拉低了整体性能。这种现象通常会在数据倾斜、资源分配不均或任务调度等方面表现出来。
数据倾斜
问题根源
数据倾斜是导致长尾任务最常见的原因。 当数据分布不均匀时,某些 Executor 会分配到比其他 Executor 多得多的数据,导致这些 Executor 上的任务运行时间过长。
解决方法
避免使用groupByKey
因为它会将所有相同键的数据聚集到一个节点上,导致数据倾斜。优先使用 reduceByKey 或 aggregateByKey 来减少数据的传输量。
数据分片
检查数据的分布情况,确保数据在不同的分区之间均匀分布。可以使用 salting 技术向键添加随机前缀,增加数据的随机性,从而减少倾斜。
使用 coalesce 或 repartition
在执行之前,使用这些函数调整分区数量以帮助平衡负载。通过合并小文件看少task的数量
使用广播小表
如果 Join 操作中有一个表比较小,可以将其广播到所有 Executor,避免数据 Shuffle。
使用 Spark SQL 的优化策略
例如,使用 skew hint 提示 Spark SQL 引擎对数据倾斜进行优化。
设置匹配的并行度
问题根源
Spark的并行度(spark.default.parallelism 和 spark.sql.shuffle.partitions 参数来设置并行度)和executor的核心数和个数不匹配
解决方法
一个Spark Application能并行的task,其实可以认为每个cpu执行一个task。所以如果有10个executor,每个executor有5个cpu,所以这个Spark Application一共可以并发执行50个task。如果配置的并行度小于50,说明资源没有充分利用,可以调整参数优化。
资源配置不合理
问题根源
如果 Executor 的资源配置过低,例如内存不足或 CPU 核数过少,会导致任务运行缓慢,窄依赖高的任务可能卡在某一个task,在sparkui中并行的task没有跑满,没有充分利用资源,都在等某一个task。
解决方法
可能是由于单个executor核心数或内存数过少,导致单个task跑的有问题。如果频繁出现,可以尝试减少executor个数,增加单个executor内存和cpu。如果是偶现的,可以看一看执行慢的task所在节点,是不是磁盘I/O存在问题。如果可以在每台机器上加装磁盘利用率,网络利用率监控是最好的。
代码逻辑不合理
去看长尾任务在做的业务逻辑,这部分业务逻辑真的一定要这么做吗,一定要这么实现吗。实现上可不可以把数据打散,分散成更多的task去并发执行。