Skip to content

调度依赖怎么设计(任务成功 ≠ 数据就绪) ​

难度与前置

难度:进阶
前置:会配工作流依赖;理解 离线幂等。
读完能做什么:用「数据就绪」而不是「任务绿勾」串依赖;失败重跑与补数不翻倍、不漏下游。

适用场景 ​

  • 上游显示成功,下游日报仍缺渠道 / 行数对不上
  • 按时钟错开跑,上游一延迟下游就读半成品或旧分区
  • 口径变更要回刷 N 天,手动点重跑漏刷下游

不适用:

  • 单机 cron、无上下游的一次性脚本
  • 实时流作业的 watermark / checkpoint(见 Flink 域)

真实场景(一条) ​

出海广告日报:全链路任务「成功」,某渠道消耗仍缺。根因是采集任务「接口没报错」即标成功,未校验预期渠道集合是否到齐;下游只挂了「上游成功」依赖,固定再 sleep 10 分钟,晚到半小时的渠道照样漏。

改造:

  1. 按 biz_date + channel 写就绪状态,全部渠道 READY 才发布日批次
  2. 下游依赖「日批次 READY」,不再依赖单纯任务状态 + 固定延时
  3. 超时告警列出缺失渠道,而不是只报「任务慢」

结果:缺数从「每周数次、业务先发现」变为「超时即告警、当晚可补」;回刷 30 天用补数功能整链跑,不再下午手工点分区。

(工具名可换成你们的:DolphinScheduler 工作流依赖 / DataWorks 依赖与补数据 / Airflow Asset。原则通用。)

怎么做(步骤清单) ​

1. 先写「产物契约」,再画依赖线 ​

每个会被下游消费的数据集,书面约定:

字段示例
业务区间dt = T-1(勿与「调度运行日」混用)
预期来源渠道集合 / 文件列表 / 上游分区集合
输入水位最晚允许事件时间或文件 mtime
质量门禁行数上下界、主键唯一、金额非空
发布含义仅当写入完整 + 校验通过 → READY

没有契约,依赖线再多也只是把「不明确」串起来。

2. 任务成功与数据就绪拆开 ​

text
任务 SUCCESS  = 进程退出码 0 / 调度器绿勾
数据 READY    = 产物可见 + 契约校验通过 + 状态发布
下游应等待的 = READY(指定 biz_date / 版本),不是「最近一次 SUCCESS」

就绪落表示意(引擎无关):

sql
-- dataset_ready:一分区一版本(迟到更正可多版本,下游记录消费版本)
INSERT INTO dataset_ready
SELECT
  'dwd_ad_spend_detail_di' AS dataset,
  '${biz_date}'            AS biz_date,
  '${output_version}'      AS version,
  'READY'                  AS status,
  current_timestamp()      AS published_at
WHERE /* 本分区校验 SQL 全部通过 */;

下游工作流依赖:

  • 优先:上游数据集 READY(或调度器里的「数据/资产依赖」)
  • 避免:仅「上游节点成功」+ 固定 sleep

3. 事件依赖代替纯时间依赖 ​

做法何时可接受风险
纯定时:A 01:00、B 03:00无上下游或强 SLA 且可接受空跑A 超时 → B 读旧/空
依赖上游成功上游成功 ≡ 数据齐(少见)成功不等于齐
依赖 READY / 分区产出默认推荐需维护就绪发布
定时 + 依赖兜底触发 + 真正门禁仍是 READY定时勿当作齐数证明

DolphinScheduler 落地要点(名称随版本略有差异):

  1. 工作流内用「依赖节点 / 上游任务状态」串同 DAG 任务
  2. 跨项目 / 跨工作流:用依赖外部工作流成功 且 自建就绪检查任务(查 dataset_ready 或目标分区 _SUCCESS/行数)
  3. 失败策略:自动重试 2~3 次;耗尽则失败,禁止用昨日分区「顶上继续」

4. 就绪发布必须「产物已可见」 ​

顺序:

text
写完整分区(或 staging 交换)→ 跑质量 SQL → 通过后写 READY / 发事件

反例:

  • 先发「可消费」事件,文件还在写 → 下游读半成品
  • 产物写完但事件丢失 → 下游干等;需对账任务定期把「有数据无 READY」修齐

大分区写法见 离线幂等 · staging 交换。

跨工作流用显式信号,不要等「整个采集 DAG 全部绿」(无关任务会拖死主题链路):

text
# 成功文件示意(HDFS / OSS 均可)
/signals/ods_ad_spend_di/dt=${biz_date}/_READY
# 内容示例:row_cnt=1234567,checksum=ab12,ready_ts=2026-09-26T08:12:00+08:00

信号至少含:table、dt、row_cnt、ready_ts(checksum 可选)。主题工作流只等「同 biz_date 的信号 + 就绪表」,与 dataset_ready 二选一或双写对账。

路径检查示意:

bash
hdfs dfs -count /warehouse/ods/ad_spend_di/dt=${biz_date}
# 期望:DIR_COUNT>=1 且 CONTENT_SIZE>0,再写 _READY

5. SLA 分级与值班看板 ​

把「跑完」改成「数据可用时刻」。级别示例(时刻按你们业务改):

级别对象示例时刻(工作日,Asia/Shanghai)违约动作
P0ads_ad_daily_report_1d09:30 前 READY紧急群 / 电话;冻结对外发布;值班补数
P1dwd_ad_spend_detail_di09:00 前 READY群告警;延迟级联;记问题单
P2探索型 ADS当日 12:00仅工单,不叫人

元数据建议字段:table / task_id | sla_level | ready_by | owner | page_channel。时区写死,避免服务器本地时扯皮。

值班看板最小集(一眼能看懂):

  1. 今日 P0/P1:计划时刻 / 实际就绪 / 状态
  2. 阻塞边:谁红了导致谁没跑
  3. 分区验收:关键表 dt 行数 vs 基线
  4. 最近一次补数 / 重跑记录(防静默改历史)

6. 失败、积压与补数(指引,不展开成长文) ​

积压先分类:

类型现象动作
资源排队等槽位扩并发 / 错峰 / 调队列
依赖一直等上游沿依赖找源头,先解源头
单任务变慢自身耗时暴涨优化 SQL/倾斜,勿全局狂点重跑

瞬时错误可自动重试 2~3 次;数据错误(空分区、主键炸)不盲重试。禁止失败后用昨日分区顶数。

重跑 / 补数只记原则,操作细节见专篇 补数与重跑怎么跑:

  1. 按血缘自上而下刷,禁止只刷当前节点
  2. 分区幂等写入(见 离线幂等)
  3. 限并发,勿打满当日集群
  4. 空分区与「未产出」显式区分

7. 迟到与多版本(避免重跑风暴) ​

  • 同一 biz_date 允许新 version(迟到渠道、口径更正)
  • 下游记录消费的上游版本;新版本按血缘有范围重算,不要全历史一把梭
  • 回刷与当日任务争资源时:独立队列 / 限流,见团队队列规范

常见坑(至少这些) ​

  1. 用时钟差代替数据依赖
    「B 比 A 晚两小时」在 A 偶发变慢时必翻车。

  2. 上游 SUCCESS 当成数据齐
    接口空响应、文件列表不全、缺渠道,任务仍可能绿。

  3. 固定 sleep 当缓冲
    10 分钟挡不住 30 分钟迟到;应监控缺失来源集合。

  4. 只补当前表、不刷下游
    明细新口径、ADS 旧口径,对账更惨。

  5. 补数用 APPEND
    同分区越补越翻倍;必须 overwrite / upsert 契约。

  6. 补数不限并发
    30 天全提交打满集群,当日 SLA 一起炸。

  7. 运行日与业务日混用
    T 日跑的任务处理 dt=T-1;依赖键必须是业务分区,不是「今天跑过」。

  8. SLA 只订「跑完」不订「数据可用」
    09:30 任务结束但 DQ 未过,业务仍不可用;SLA 对齐 READY / 验收通过时刻。

  9. 跨工作流等「整 DAG 全绿」
    无关叶子任务拖死主题链路;应等同 biz_date 的 _READY / 就绪表。

如何验收(带数字的前后对比) ​

指标改前(示例)改后(目标)
「任务全绿但仍缺数」次数 / 周如 ≥ 20(缺数应在就绪超时告警暴露)
缺数发现方业务先发现调度/质量告警先发现
就绪超时告警是否带出缺失来源否是(渠道/文件列表)
回刷 30 天耗时与漏刷如半天手工 + 漏下游批量补数整链完成、下游版本一致
同分区连续补两遍核心指标可能翻倍金额/行数一致

Checklist:

  • [ ] 每个跨任务消费的数据集有书面产物契约
  • [ ] 下游依赖 READY(或等价分区检查),不是纯定时
  • [ ] 失败重试次数与告警接收人已配置;禁止失败后用旧分区顶数
  • [ ] 补数工单含血缘下游清单 + 并发上限
  • [ ] P0/P1 有 ready_by + owner + 告警渠道;值班看板四项齐
  • [ ] 跨工作流有 _READY 或等价就绪表,且内容含 dt / row_cnt / ready_ts
  • [ ] 人为制造上游空分区:下游未启动且有告警
  • [ ] 与 数据质量闭环 的校验可挂到就绪门禁上
  • [ ] 补数操作走 补数与重跑,本篇不替代操作手册
text
验收记录模板:
工作流 / 数据集:
业务日:
READY 发布时间:
预期来源数 / 实际 READY 来源数:
下游消费版本:
同分区重跑两次 diff:
签字:

改上游表或口径导致依赖面变化时,配合 改表前影响评估 更新 READY 与通知面。

相关面试题 ​

题库小程序链接待定;先用站内锚点占位。

  • [ ] 题:上游任务成功为什么下游仍可能缺数?(考察点:任务绿 ≠ 数据就绪;依赖 READY)→ 占位:#todo-interview-dependency-green-vs-ready
  • [ ] 题:跨工作流 READY 信号最少含哪些字段?(考察点:dt/row_cnt/ready_ts)→ 占位:#todo-interview-dependency-ready-fields
  • [ ] 题:人为制造上游空分区,下游应表现什么?(考察点:未启动且有告警)→ 占位:#todo-interview-dependency-empty-upstream
  • [ ] 题:补数工单缺什么会漏刷下游?操作应走哪条路径?(考察点:血缘下游清单 + 并发上限;操作走 补数/重跑/追数)→ 占位:#todo-interview-dependency-backfill-lineage
  • [ ] 题:同分区连续补两遍,核心指标应怎样?(考察点:金额/行数一致,不翻倍)→ 占位:#todo-interview-dependency-double-catchup

改写说明:综合 Wood 日课·调度依赖 / 调度运维与面试问「任务成功 ≠ 数据就绪」;并入原 dependency-sla 的 SLA 分级、值班看板与 _READY 信号。补数操作见 rerun-catchup。无未公开公司数据。