2. Airflow基础回顾

在进入数据依赖与补数回填的实战之前,我们必须先把 Airflow 的“骨架”重新梳理一遍。很多同学在写 DAG 时觉得“能跑就行”,但一旦遇到依赖错乱、任务卡住、回填失败,就会发现自己对 Scheduler、Executor、Metadata Database 之间的协作关系并不清楚。本节将围绕 DAG、Task、Operator、Scheduler、Executor、Metadata Database 六大核心组件,讲清它们各自的职责与协同机制,为后续的依赖管理与补数回填打下坚实基础。

一、核心组件职责拆解

Airflow 本质上是一个“编排调度系统”,它并不负责计算本身,而是负责决定“什么任务、在什么时间、以什么顺序、由谁执行”。理解这一点,才能理解各组件的分工。

  • DAG(有向无环图):描述任务之间的依赖关系与调度周期,是逻辑层面的“工作流定义”。DAG 本身不执行任何计算,它只是一份声明。
  • Task(任务):DAG 中的一个节点,代表一个具体的执行单元。Task 是 DAG 的实例化节点,携带依赖关系与重试策略。
  • Operator(算子):Task 的“模板”,决定这个任务具体做什么,例如 BashOperator、PythonOperator、SQLExecuteQueryOperator。Operator 是能力的封装,Task 是 Operator 的运行时实例。
  • Scheduler(调度器):Airflow 的“大脑”,负责解析 DAG 文件、判断依赖是否满足、生成 DagRun 与 TaskInstance,并把可执行任务推给 Executor。
  • Executor(执行器):负责真正“跑任务”的组件,决定任务在本地进程、Celery 队列还是 Kubernetes Pod 中执行。
  • Metadata Database(元数据库):Airflow 的“记忆中枢”,存储 DAG 结构、任务状态、调度历史、变量、连接等所有状态信息。Scheduler 与 Executor 都依赖它来协调。
一句话记忆:DAG 定义“做什么”,Scheduler 决定“何时做”,Executor 负责“谁来做”,Metadata Database 记录“做到哪了”。

二、运行机制:一次调度的完整链路

理解组件之后,我们来看一次典型的调度是如何发生的。假设你有一个每天凌晨 2 点运行的 DAG,包含 extract → transform → load 三个任务。

  1. Scheduler 周期性扫描 DAG 目录,解析 DAG 文件,将 DAG 结构与调度周期写入 Metadata Database。
  2. 到达调度时间点后,Scheduler 在元数据库中创建一条 DagRun 记录,表示“本次调度已触发”。
  3. Scheduler 根据依赖关系,为每个 Task 创建 TaskInstance,并判断其依赖是否满足。
  4. 依赖满足的 TaskInstance 被放入 Executor 的执行队列。
  5. Executor 拉起 Worker(或本地进程)执行 Operator 逻辑,执行结果与日志状态回写 Metadata Database。
  6. 下游任务看到上游状态变为 success 后,被 Scheduler 解锁并继续执行,直到整个 DagRun 完成。

可以看到,Metadata Database 是整个链路的“唯一真相来源”。Scheduler 不直接与 Worker 通信,而是通过数据库状态来协调。这也是为什么数据库性能会直接影响调度延迟。

Airflow 核心组件协作关系 DAG 文件 依赖 + 调度周期 Scheduler 解析 / 判断 / 触发 Executor 本地 / Celery / K8s Metadata DB DagRun / TaskInstance Worker 执行 Operator 日志 / 状态 回写结果 状态查询

三、关键概念对照清单

为了便于后续章节查阅,这里用一张表把容易混淆的概念对齐清楚。

概念 层级 核心作用 常见误区
DAG 逻辑定义 描述依赖与调度周期 误以为 DAG 会执行任务
Task DAG 节点 依赖关系中的执行单元 与 Operator 混为一谈
Operator 能力模板 定义任务具体做什么 认为 Operator 就是 Task
Scheduler 调度中枢 解析、判断、触发任务 以为它直接执行任务
Executor 执行中枢 决定任务在哪里运行 忽略其与队列的关系
Metadata DB 状态存储 保存所有运行状态 忽视其性能瓶颈

四、案例与常见误区复盘

来看一个真实场景:某团队配置了 CeleryExecutor,DAG 每天运行正常,但某天开始任务大量延迟。排查后发现,Scheduler 仍在正常触发 DagRun,但 TaskInstance 长时间停留在 queued 状态。原因不是 DAG 写错,而是 Celery Worker 数量不足,任务堆积在队列中。这个案例说明:调度成功 ≠ 执行成功,Scheduler 与 Executor 是两个独立环节。

# 查看任务实例状态(示例)
airflow tasks states my_dag extract 2024-06-01

# 常见状态
# queued     -> 已进入执行队列,等待 Worker
# running    -> Worker 正在执行
# success    -> 执行成功
# failed     -> 执行失败,等待重试或人工处理
# up_for_retry -> 等待重试
误区一:把 DAG 文件当成“程序”来理解。DAG 文件只是声明,真正的执行发生在 Worker 中。
误区二:忽略 Metadata Database 的重要性。数据库慢,Scheduler 解析和状态更新都会变慢,表现为“调度延迟”。
误区三:认为 Executor 只影响性能。Executor 类型决定了任务的隔离性、并发能力和失败恢复方式,直接影响补数回填策略。
建议在本地开发时使用 SequentialExecutor 或 LocalExecutor 快速验证 DAG 逻辑;在生产环境根据并发规模选择 CeleryExecutor 或 KubernetesExecutor,并重点关注 Metadata Database 的连接池与索引优化。

回顾本节,DAG、Task、Operator 属于“定义层”,Scheduler、Executor 属于“运行层”,Metadata Database 则是贯穿两者的“状态层”。只有把这三层关系理清,后续我们讨论数据依赖、触发规则、补数回填时,才能准确判断问题出在定义、调度还是执行环节。