聊这个问题的原因是,本周在测试环境遇到了一例从Spark往S3写数据失败的情况,花了些时间来搞清楚个中缘由,这里整理出来与大家分享,期望能对同道中人有所帮助。
背景
在笔者的数据系统中,每天会定时启动一个Spark批处理程序,对前一天的流处理结果进行合并、整理,然后写入AWS S3,从而提供尽可能快的冷数据查询(基于Presto SQL)。写数据的方式很简单,通过调用Spark DataFrame的write接口来完成的。
df.write.parquet("s3://qa-s3-data-merge-uw2/type=security/ts_interval=1550448000")
本周在测试环境做压力测试时,发现了一例程序处理失败的情况,所报的错误如下(已简化)。结合这个错误信息和Spark批处理程序运行的其他日志来看,当时写数据的Task已经成功将数据写入到了相关的temporary目录下,但是在Driver中执行commitJob将文件从temporary目录Rename到正式目录时失败了。
java.io.IOException: Failed to rename FileStatus{path=s3://qa-s3-data-merge-uw2/type=security/ts_interval=1550448000/_temporary/0/task_20190219103051_0010_m_000008/s3_partition_id=51/part-00008-936a4f3b-8f71-48ce-960a-e60d3cf4488f.c000.snappy.parquet; isDirectory=false; length=95831; replication=1; blocksize=67108864; modification_time=1550572263000; access_time=0; owner=hadoop; group=hadoop; permission=rw-rw-rw-; isSymlink=false} to s3://qa-s3-data-merge-uw2/type=security/ts_interval=1550448000/s3_partition_id=51/part-00008-936a4f3b-8f71-48ce-960a-e60d3cf4488f.c000.snappy.parquet
at org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter.mergePaths(FileOutputCommitter.java:415)
at org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter.mergePaths(FileOutputCommitter.java:428)
at org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter.mergePaths(FileOutputCommitter.java:428)
at org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter.commitJobInternal(FileOutputCommitter.java:362)
at org.apache.hadoop.mapreduce.lib.output.FileOutputCo