我有一个Spark应用程序,可以读取CSV并写入Parquet文件。
在某些情况下(分配的内存太少,执行器丢失),Parquet任务可能会失败并重试;我注意到在这种情况下有重复的记录,即一些CSV文件在重试时多次写入Parquet文件中。
如何避免此类重复?我已经使用了--conf spark.yarn.maxAppAttempts=1
,但这仅适用于工作,而不适用于任务。如果某一阶段失败,应用程序是否应该失败,或者是否有任何回滚方法?
答案 0 :(得分:2)
Spark使用FileOutputCommitter
管理暂存输出文件和最终输出文件。
FileOutputCommitter
的行为直接影响写入数据的作业的性能。它有两种方法,commitTask
和commitJob
。
Apache Spark 2.0和更高版本使用Apache Hadoop 2,后者使用mapreduce.fileoutputcommitter.algorithm.version
的值来控制commitTask和commitJob的工作方式。
当前,Spark附带两种默认的Hadoop提交算法-版本1和版本2。
在版本1 中,commitTask将任务生成的数据从任务临时目录移动到作业临时目录,当所有任务完成时,commitJob将数据从作业临时目录移动到最终目标。这样可以确保作业级别的交易记录。
在版本2 中,commitTask会将任务生成的数据直接移动到最终目的地,并且commitJob基本上是无操作的。这样可以确保任务级的事务性写。如果重新提交作业,您可能会看到重复的内容。
根据您的情况,设置dataframe.write.option("mapreduce.fileoutputcommitter.algorithm.version", "1")
以确保事务性写在作业级别。
参考:https://databricks.com/blog/2017/05/31/transactional-writes-cloud-storage.html