Spark作业跑到一半Task失败了——容错机制怎么工作的?
先说结论
Spark的容错分三个层次:
Task失败: 自动重试(默认4次),不需要重启整个Stage
Executor失败: YARN自动启动新Executor,重新执行该Executor上的Task
Driver失败: 整个作业失败,需要外部调度系统重启
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
Spark的容错机制是它在生产环境可靠运行的基础。理解容错机制有助于你判断“什么时候作业会自动恢复、什么时候必须介入”。今天把Task失败、Executor失败、Driver失败三个层次的容错讲清楚。
Task级别容错
每个Task失败后会自动重试,默认最多重试spark.task.maxFailures = 4次。超过后整个Stage失败。
// Task重试配置
spark.conf.set("spark.task.maxFailures", "4") // 默认4次
// 你在Spark UI里可以看到:
// - Task的Attempt号(0, 1, 2...)表示重试了几次
// - 失败原因(OOM、网络超时、Shuffle Fetch失败等)
常见的Task失败原因:数据倾斜导致OOM、网络闪断导致Shuffle Fetch失败、目标存储不可用。如果是网络闪断这种临时性问题,重试就能解决。如果是OOM,重试多少次都会失败。
Executor级别容错
当Executor崩溃时(OOM、硬件故障等),YARN会自动启动一个新的Executor。崩溃的Executor上正在运行的Task会被重新调度到其他Executor上执行。
但有一个问题:如果崩溃的Executor上有Shuffle数据,这些Shuffle数据就丢了。下游要拉取这些Shuffle数据的Task会失败(FetchFailedException),Spark会重新执行产生这些Shuffle数据的上游Stage。
这就是为什么建议开启External Shuffle Service —— Shuffle数据由NodeManager管理,Executor崩溃不会丢失Shuffle数据。
Driver级别容错
Driver失败 = 整个作业失败。Spark自身没有Driver自动恢复的机制。需要依赖外部调度系统(Airflow、DataWorks、Databricks Workflows)重新提交作业。
所以生产环境的ETL作业必须配置失败重试。我们的规矩是每个作业最多重试3次,间隔5分钟。
总结
| 失败层次 | 恢复方式 | 是否自动 |
|---|---|---|
| Task失败 | 自动重试(默认4次) | ✔ 自动 |
| Executor失败 | YARN启动新Executor + 重调度Task | ✔ 自动 |
| Shuffle数据丢失 | 重新执行上游Stage | ✔ 自动(但慢) |
| Driver失败 | 整个作业失败,需外部重启 | ✖ 手动/调度系统 |
Task和Executor的容错是自动的,Driver的容错需要调度系统。面试时能说清楚三个层次的容错机制和“FetchFailedException的根因是Shuffle数据丢失”,就很有深度。
下一篇聊一个很多人拿不准的问题:并行度设多少合适?Task数量和分区数怎么定?
你们生产环境遇到过FetchFailedException吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长