Spark任务/Executor失败时不同存储的重复记录问题咨询
Spark JDBC读+写入不同存储的容错行为分析
一、关于HDFS的错误认知纠正
你的理解存在偏差,Spark任务失败重试时,HDFS写入可能出现数据重复,但数据丢失概率极低:
- 任务失败重试时,Spark会重新执行对应分区的JDBC查询与写入操作。若之前失败的任务已成功写入部分数据到HDFS(比如任务执行中途崩溃),重试时会重写整个分区,导致HDFS出现重复的分区文件。尽管Spark默认的
FileOutputCommitter(version 1)会先写入临时目录、最后提交时再移动到目标路径,能避免大部分重复,但如果在提交阶段崩溃,重试后仍可能出现重复文件。 - 数据丢失情况极少:HDFS本身是多副本存储,且Spark写入时会先生成临时文件,确认写入成功后才重命名为正式文件,除非HDFS集群遭遇灾难性故障,否则几乎不会丢失数据。另外,若JDBC读取的是动态变化的数据(而非静态快照),两次查询结果可能不一致,进而导致写入数据的逻辑不一致。
二、最终一致性存储S3的表现
- 写入层面:S3的PUT操作存在最终一致性特性(新创建对象为强一致,但覆盖/删除后重新PUT为最终一致),Spark任务重试时会出现以下问题:
- 临时文件写入后,重命名到正式路径的操作可能存在延迟,Spark可能判定之前的写入未完成,进而再次写入,导致S3中出现重复文件。
- 若任务在提交阶段崩溃,S3上可能残留临时文件,或正式文件处于“可见但不可读”的中间状态,后续重试可能写入重复数据,需手动清理临时文件。
- 读取层面:尽管当前S3多数区域已支持写入后的强一致性读取,但覆盖/删除操作后的读取仍为最终一致,若Spark作业依赖刚写入S3的数据,可能出现读取失败的情况。
三、强一致性存储GCS Bucket的表现
GCS提供全操作的强一致性支持(包括PUT、GET、DELETE等),其表现比HDFS更稳定:
- 写入时,临时文件重命名到正式路径的操作是原子性的,任务失败重试时,Spark能精准判断之前的写入是否成功,不会出现重复写入(除非任务自身逻辑存在问题)。
- 写入成功后可立即读取到数据,不存在S3的最终一致性延迟问题。
- 数据丢失概率极低,GCS的多副本与容错机制能有效保障数据安全。
四、使用S3作为目标存储的隐患
- 数据重复风险:受最终一致性与Spark提交机制影响,任务重试后极易产生重复文件,需后续通过
distinct操作或离线去重任务清理,增加额外工作量。 - 临时文件残留:任务崩溃后,S3上的临时文件不会自动清理,长期积累会占用存储空间,需手动或定时任务清理。
- 一致性延迟问题:若作业存在写后读的依赖逻辑,可能出现读取不到刚写入数据的情况,导致作业失败或数据不一致。
- 性能波动:S3的访问速度受网络与AWS服务状态影响,相比HDFS和GCS,性能波动更大,可能拖慢Spark作业的执行效率。
内容的提问来源于stack exchange,提问作者Siddhartha Sadhukhan
相关产品推荐
相关产品推荐

