DAG 是什么
DAG(有向无环图)是调度系统表达依赖的方式:节点是一次具体的执行(跑 SQL、执行脚本、等待文件),边表示「上游成功后下游才能开始」,无环保证一定存在可执行的先后顺序。界面上看到的任务图,就是排查「为什么这个任务还没跑」的第一入口。
依赖的粒度决定可维护性
依赖拆得越细,失败重跑的范围越小、定位越快;拆得过粗(整条链路一个大 DAG),任何一处失败都要从上游重跑。常见折衷是按主题域拆分 DAG,域内按表级依赖串联,域之间用少数几个关键节点连接。
基本信息
| 节点 | 一个任务或算子:跑 SQL、执行脚本、等待文件或检查行数 |
|---|---|
| 边 | 依赖关系:上游成功后才调度下游 |
| 约束 | 不允许循环依赖,否则无法确定执行顺序 |
| 依赖类型 | 数据依赖、时间依赖、外部依赖(接口、人工确认) |
| 拆分建议 | 按主题域拆分 DAG,域内细粒度、域间少量连接 |
依赖类型与表达方式
| 依赖类型 | 含义 | 表达方式 |
|---|---|---|
| 时间依赖 | 每天固定时间触发 | cron 表达式 |
| 数据依赖 | 上游表分区或文件已就绪 | 上游任务节点或分区检查节点 |
| 跨系统依赖 | 依赖外部接口或别的调度平台 | HTTP 检查节点或外部任务节点 |
| 人工确认 | 需要人工判断后才能继续 | 人工确认节点,避免直接串自动化 |
典型使用场景
- 日批链路:抽取、清洗、汇总、导出按依赖串联
- 多源汇合:多个上游都成功后触发宽表加工
- 数据就绪触发:以分区或文件出现作为条件,而不是固定时间
- 局部重跑:只重跑失败的子树,不影响已经成功且结果正确的部分
- 排障定位:沿依赖图从上往下找第一个未完成或失败的节点
依赖关系示意
依赖关系示意
# 两个上游汇合到一条汇总链路,任意一个上游失败都会阻塞下游
extract_orders ─→ transform_orders ─→ load_dwd ─┐
extract_users ─→ build_dim_users ───────────────┴→ ads_sales_daily
# 排查思路:下游一直「等待中」时,沿边往上找第一个状态异常的上游节点Airflow 中的依赖写法
Airflow 中的依赖写法
with DAG(dag_id="daily_sales", schedule="0 2 * * *", start_date=datetime(2026, 1, 1), catchup=False) as dag:
extract = BashOperator(task_id="extract_orders", bash_command="echo extract")
dim = BashOperator(task_id="build_dim_users", bash_command="echo dim")
load = BashOperator(task_id="load_dwd", bash_command="echo load")
ads = BashOperator(task_id="ads_sales_daily", bash_command="echo ads")
extract >> load # extract 成功后才跑 load
dim >> ads # 维度建好后才跑汇总
load >> ads # 两个上游都完成,ads 才可调度把「等上游产出」建成显式依赖,比在下游里 sleep 半小时可靠得多:既能让调度器在数据就绪后立刻触发,也能在界面上直接看出到底卡在哪一环。
循环依赖(A 等 B、B 等 A)在部分平台上不报错但永远不会执行,表现为任务长期处于等待状态;建模完成后先看一遍依赖图是否存在环路。