首页/数据/数据工程与 ETL 速查/DAG 有向无环图与依赖建模

DAG 有向无环图与依赖建模

DAG 用节点表示任务、边表示依赖,无环保证“总能排序执行完”。可视化 DAG 是排查“为什么还没跑”的常用入口:上游没完成,下游只会等待。

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)在部分平台上不报错但永远不会执行,表现为任务长期处于等待状态;建模完成后先看一遍依赖图是否存在环路。

易错点

  • 循环依赖在部分平台不报错但永不执行,任务长期停留等待状态,需靠人工看图才能发现
  • 依赖粒度太粗(整库一个大 DAG),局部失败牵连全链路,每次重跑都耗时数小时
  • 用固定 sleep 代替数据依赖,上游变慢时下游读到不完整数据,且没有任何报错
  • 在依赖图上堆叠人工节点却不加说明,交接后没人知道该在什么条件下确认

数据来源与参考

  • Apache Airflow 官方文档:DAGs
  • Apache DolphinScheduler 官方文档:工作流定义
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌