外观
调度依赖怎么设计(任务成功 ≠ 数据就绪)
难度与前置
难度:进阶
前置:会配工作流依赖;理解 离线幂等。
读完能做什么:用「数据就绪」而不是「任务绿勾」串依赖;失败重跑与补数不翻倍、不漏下游。
适用场景
- 上游显示成功,下游日报仍缺渠道 / 行数对不上
- 按时钟错开跑,上游一延迟下游就读半成品或旧分区
- 口径变更要回刷 N 天,手动点重跑漏刷下游
不适用:
- 单机 cron、无上下游的一次性脚本
- 实时流作业的 watermark / checkpoint(见 Flink 域)
真实场景(一条)
出海广告日报:全链路任务「成功」,某渠道消耗仍缺。根因是采集任务「接口没报错」即标成功,未校验预期渠道集合是否到齐;下游只挂了「上游成功」依赖,固定再 sleep 10 分钟,晚到半小时的渠道照样漏。
改造:
- 按
biz_date + channel写就绪状态,全部渠道 READY 才发布日批次 - 下游依赖「日批次 READY」,不再依赖单纯任务状态 + 固定延时
- 超时告警列出缺失渠道,而不是只报「任务慢」
结果:缺数从「每周数次、业务先发现」变为「超时即告警、当晚可补」;回刷 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 落地要点(名称随版本略有差异):
- 工作流内用「依赖节点 / 上游任务状态」串同 DAG 任务
- 跨项目 / 跨工作流:用依赖外部工作流成功 且 自建就绪检查任务(查
dataset_ready或目标分区_SUCCESS/行数) - 失败策略:自动重试 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,再写 _READY5. SLA 分级与值班看板
把「跑完」改成「数据可用时刻」。级别示例(时刻按你们业务改):
| 级别 | 对象示例 | 时刻(工作日,Asia/Shanghai) | 违约动作 |
|---|---|---|---|
| P0 | ads_ad_daily_report_1d | 09:30 前 READY | 紧急群 / 电话;冻结对外发布;值班补数 |
| P1 | dwd_ad_spend_detail_di | 09:00 前 READY | 群告警;延迟级联;记问题单 |
| P2 | 探索型 ADS | 当日 12:00 | 仅工单,不叫人 |
元数据建议字段:table / task_id | sla_level | ready_by | owner | page_channel。时区写死,避免服务器本地时扯皮。
值班看板最小集(一眼能看懂):
- 今日 P0/P1:计划时刻 / 实际就绪 / 状态
- 阻塞边:谁红了导致谁没跑
- 分区验收:关键表
dt行数 vs 基线 - 最近一次补数 / 重跑记录(防静默改历史)
6. 失败、积压与补数(指引,不展开成长文)
积压先分类:
| 类型 | 现象 | 动作 |
|---|---|---|
| 资源 | 排队等槽位 | 扩并发 / 错峰 / 调队列 |
| 依赖 | 一直等上游 | 沿依赖找源头,先解源头 |
| 单任务变慢 | 自身耗时暴涨 | 优化 SQL/倾斜,勿全局狂点重跑 |
瞬时错误可自动重试 2~3 次;数据错误(空分区、主键炸)不盲重试。禁止失败后用昨日分区顶数。
重跑 / 补数只记原则,操作细节见专篇 补数与重跑怎么跑:
- 按血缘自上而下刷,禁止只刷当前节点
- 分区幂等写入(见 离线幂等)
- 限并发,勿打满当日集群
- 空分区与「未产出」显式区分
7. 迟到与多版本(避免重跑风暴)
- 同一
biz_date允许新version(迟到渠道、口径更正) - 下游记录消费的上游版本;新版本按血缘有范围重算,不要全历史一把梭
- 回刷与当日任务争资源时:独立队列 / 限流,见团队队列规范
常见坑(至少这些)
用时钟差代替数据依赖
「B 比 A 晚两小时」在 A 偶发变慢时必翻车。上游 SUCCESS 当成数据齐
接口空响应、文件列表不全、缺渠道,任务仍可能绿。固定 sleep 当缓冲
10 分钟挡不住 30 分钟迟到;应监控缺失来源集合。只补当前表、不刷下游
明细新口径、ADS 旧口径,对账更惨。补数用 APPEND
同分区越补越翻倍;必须 overwrite / upsert 契约。补数不限并发
30 天全提交打满集群,当日 SLA 一起炸。运行日与业务日混用
T 日跑的任务处理dt=T-1;依赖键必须是业务分区,不是「今天跑过」。SLA 只订「跑完」不订「数据可用」
09:30 任务结束但 DQ 未过,业务仍不可用;SLA 对齐 READY / 验收通过时刻。跨工作流等「整 DAG 全绿」
无关叶子任务拖死主题链路;应等同biz_date的_READY/ 就绪表。
如何验收(带数字的前后对比)
| 指标 | 改前(示例) | 改后(目标) |
|---|---|---|
| 「任务全绿但仍缺数」次数 / 周 | 如 ≥ 2 | 0(缺数应在就绪超时告警暴露) |
| 缺数发现方 | 业务先发现 | 调度/质量告警先发现 |
| 就绪超时告警是否带出缺失来源 | 否 | 是(渠道/文件列表) |
| 回刷 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。无未公开公司数据。