Spark RDD分区写入S3时最后少量任务卡顿的优化方案咨询
你遇到的是典型的Spark分区写入数据倾斜问题。你目前按year/month/submitDate三级分区写入,9月1日的数据占了全量数据的绝大多数,Spark默认按分区键的值分配处理任务,所有9月1日的计算和写入压力都集中在少数Task上,就是你看到的最后16个长时间运行的任务,其他日期数据量小,对应的Task很快就能跑完。
优化方案
1. 核心问题解决:对倾斜分区加盐打散
不要直接用原生的partitionBy写入,先给倾斜的分区键加随机后缀打散:
- 给
submitDate为9月1日的数据新增一个加盐的分区字段,比如生成分区键submitDate_salted,值为原submitDate拼接0~N的随机数(N根据倾斜程度调整,比如设为20,就可以把原来1个倾斜分区拆成20个均匀的小分区),其他日期的数据保持原submitDate值即可。 - 写入时用
submitDate_salted代替原来的submitDate作为最后一级分区键,这样原来集中在16个Task的压力会平摊到N*16个Task上,完全解决负载不均的问题。 - 后续查询时如果需要按日期过滤,要么保留原
submitDate作为数据列直接过滤,要么通过input_file_name()提取路径中的日期前缀即可,不会影响业务使用。
2. 关于新增日期分区键的疑问
你当前已经有submitDate作为日期维度的分区键,额外新增重复的日期字段做分区键没有任何作用,既解决不了数据倾斜问题,也达不到负载均衡的效果,反而会冗余占用存储空间,不建议这么做。
3. S3写入通用优化项
- 调整写入前分区大小:写入前通过
repartition()调整DataFrame分区数,控制每个分区大小在128MB256MB区间,你当前总Shuffle数据量为1.2T左右,建议调整分区数为40008000,避免单分区过大。 - 启用S3A客户端加速配置:如果你用Hadoop S3A客户端访问S3,可以添加以下Spark配置提升写入性能:
spark.hadoop.fs.s3a.fast.upload true spark.hadoop.fs.s3a.multipart.size 67108864 spark.hadoop.fs.s3a.connection.maximum 100
- 按需关闭缓存:如果你的数据仅做一次写入,写完即清理,
cacheDataBeforeSave配置可以关闭,避免额外的内存开销拖慢任务速度。 - 控制小文件数量:如果单个分区下生成的小文件过多,可以写入前用
sortWithinPartitions按分区键排序,减少最终输出的文件数。
内容的提问来源于stack exchange,提问作者Anupam
相关产品推荐
相关产品推荐

