批处理系统失效恢复(三):任务编排与依赖图,把重跑变成图上的局部操作

系列索引:① 失效的发现与止血 | ② 幂等与断点续跑 | ③ 任务编排与依赖图(本篇)

前两篇解决了「单个任务重跑不闯祸」,这篇往上走一层:几十上百个任务互相依赖的批处理系统,一个任务挂了,哪些下游要重跑、哪些不用、以什么顺序重跑——这是编排层的功课。把依赖关系建成显式的图,这些问题的答案就从「老师傅的脑子和脚本」变成「图上的一次局部遍历」。

先看没有依赖图的世界

多数批处理系统的任务依赖长这样:任务 A 的脚本末尾 shell 里调任务 B,B 的末尾调 C。依赖关系散落在几百行脚本里,没人能完整回答「D 挂了会影响谁」。重跑范围只能靠「全跑一遍」——安全但昂贵,或者靠老员工记忆——快但危险。人员一流动,系统就成了黑盒。

显式依赖图的三件套

  1. DAG 声明:任务间的依赖用配置声明(A→B 表示 B 依赖 A),而不是藏在脚本调用里。调度框架(Airflow 类)都支持,关键是要有纪律:所有依赖必须进 DAG,禁止脚本内私拉调用。
  2. 状态继承:每个任务节点记录自己的状态与产出指纹(输出的数据版本号)。重跑判定变成图查询:D 失败,沿 DAG 找 D 的后代集合,且只重跑「上游全部成功且自身未成功」的节点。
  3. 数据版本对齐:重跑 D 时,D 的下游要不要用 D 的新输出重算?取决于业务对一致性的要求。把「重跑范围」做成可配置(只重跑 D / 重跑 D 及直接下游 / 重跑整个子图),比每次临时拍板体面得多。

一个实战例子

数据仓库场景:ods 层 20 个抽取任务 → dwd 层 15 个清洗任务 → dws 层 10 个聚合 → 报表层 8 个任务。某天 dwd_07 因上游数据迟到失败。有依赖图的处置:定位 dwd_07 的后代(3 个 dws + 2 个报表),上游补数成功后,调度器自动按拓扑序重跑这 5 个任务,全程十分钟。没有依赖图的处置:值班同学翻脚本找依赖,漏了一个报表任务,第二天早上被业务方发现数字对不上——真实故事,那位同学现在是我们组的 DAG 纪律委员。

编排层的两个进阶设计

检查点粒度对齐任务粒度:②篇的断点续跑在单任务内做检查点,编排层把检查点提升到任务级——任务完成即记录(含数据指纹),两级检查点配合,任何一层失效都能最小范围恢复。

优先级与资源编排:重跑的子图和日常调度抢资源时,按业务优先级排队(财报类任务优先于分析类)。DAG 加上优先级标注,资源紧张时的调度决策也就自动化了。

系列收官

三篇串起来:①发现与止血(分钟级响应)→ ②幂等与断点(重跑安全)→ ③依赖图(重跑精准)。批处理的可靠性不是靠某一个银弹,是这三层一起把「故障恢复」从人力密集型变成系统自动化。系列之后计划写存储层的一致性快照——批处理和存储的交界处,还有一批好坑。


写文里这些翻译场景,来自我日常在用的「随心翻译」:Edge/Chrome 浏览器插件,本地优先架构,不用不花钱。官网 suanlinfang.cn/translate?from=cnblogs

posted @ 2026-10-17 09:34  吴键WJ  阅读(13)  评论(0)    收藏  举报