1. 课程导入

欢迎进入《Airflow数据依赖与补数回填实战》。在真实的数据平台里,调度系统最容易被低估、却最容易在关键时刻“掉链子”的能力,不是把任务按时跑起来,而是在数据尚未就绪时不误跑,在历史数据需要重算时能安全、可控、可追溯地补齐。这两件事,正好对应 Airflow 中两个高频且高价值的主题:数据依赖(Data Dependency)与补数回填(Backfill)。

很多团队最初使用 Airflow,只把它当作“定时器 + 任务执行器”:每天凌晨触发 DAG,任务按顺序执行。但随着业务复杂度上升,问题会迅速暴露:上游表还没产出,下游任务已经开跑;某个分区数据延迟到达,昨天的报表需要重算;补数时不小心触发了当天任务,造成重复写入;回填几十天数据时,并发过高把数据库压垮。这些问题的根源,往往不是任务代码写错了,而是依赖关系没有表达清楚,回填策略没有设计好。

本节的学习目标不是记住几个 API,而是建立一套判断框架:什么时候该用时间依赖,什么时候必须用数据依赖;补数时如何控制并发、幂等与影响范围;如何通过日志和元数据验证回填结果是否符合预期。

学习目标与核心价值

完成本章后,你应当能够:

  • 理解 Airflow 中逻辑日期、数据区间与任务实例之间的关系,避免把“执行时间”误当成“数据时间”。
  • 掌握数据依赖的常见表达方式,包括 ExternalTaskSensor、数据集(Dataset / Asset)触发、以及基于元数据或存储检查的自定义依赖。
  • 能够设计可回填的 DAG:任务幂等、分区明确、参数化清晰、失败可重试。
  • 掌握 airflow dags backfill 与 UI 回填的差异,理解 --start-date、--end-date、--max-active-runs 等关键参数的作用。
  • 能够识别并规避补数中的典型误区:重复写入、依赖错位、并发失控、回填范围过大。

核心价值可以概括为一句话:让数据在正确的时间、基于正确的输入、以可控的方式被计算和重算。这直接决定了数据仓库、特征平台和报表系统的可信度。

整体课程框架

本课程共 30 章,围绕“依赖—回填—验证—优化”的主线展开。前段建立概念与模型,中段进入实战配置与代码,后段聚焦排障、性能与生产规范。你可以把它看作一条从“能跑”到“跑得稳、补得准”的进阶路径。

阶段主题范围关键产出
基础认知逻辑日期、数据区间、任务实例、依赖类型能准确描述一次调度背后的数据含义
依赖实战ExternalTaskSensor、Dataset 触发、自定义检查能表达跨 DAG、跨系统的数据就绪条件
回填实战CLI 回填、UI 回填、参数控制、并发限制能安全补齐指定日期范围的数据
验证与排障日志分析、元数据核对、幂等验证能判断回填是否成功且无副作用
生产规范幂等设计、分区策略、监控告警、成本控制形成可复用的团队规范

核心原理:依赖与回填的本质

Airflow 的调度模型建立在“逻辑日期”之上。一个 DAG Run 对应一个逻辑日期,任务实例在该日期下执行。逻辑日期通常表示数据区间,而不是任务实际开始的时间。例如,处理 2024-06-01 这一天的数据,逻辑日期可能是 2024-06-01,但任务实际在 2024-06-02 凌晨执行。理解这一点,是理解依赖与回填的前提。

数据依赖的本质,是把“上游数据是否就绪”这一外部事实,转化为调度系统可判断的条件。时间依赖只能回答“到点了吗”,数据依赖才能回答“数据到了吗”。补数回填的本质,则是对历史逻辑日期重新发起 DAG Run,并确保每个日期区间的计算是独立、幂等、可重复的。

逻辑日期 · 数据区间 · 回填范围的关系 逻辑日期 2024-06-01 DAG Run 的标识 数据区间 [00:00, 24:00) 实际处理的数据范围 回填范围 start ~ end 逐逻辑日期重跑 依赖判断点 上游数据是否就绪? → 时间依赖只能判断“到点”,数据依赖才能判断“数据到了” 幂等任务 同一逻辑日期重跑结果一致 非幂等任务 重跑导致重复写入或数据膨胀

方法流程:从依赖设计到安全回填

一个可回填的 DAG,通常遵循以下流程:

  1. 明确数据区间:确定每个逻辑日期对应的数据范围,并在任务中通过模板变量或参数传入。
  2. 表达依赖条件:根据上游是同一 DAG、跨 DAG 还是外部系统,选择传感器、数据集触发或自定义检查。
  3. 保证任务幂等:写入前先删除或覆盖目标分区,或使用 MERGE / UPSERT 语义,避免重复数据。
  4. 控制回填范围与并发:使用 --max-active-runs 限制同时运行的 DAG Run 数量,避免压垮数据库。
  5. 验证结果:核对行数、分区、关键指标,并检查日志中是否有跳过或异常。
# 示例:限制并发并回填指定日期范围
airflow dags backfill example_dag \
  --start-date 2024-06-01 \
  --end-date 2024-06-07 \
  --max-active-runs 2 \
  --reset-dagruns

回填前先在小范围(如 1 天)验证幂等性和依赖行为,再扩大范围。生产环境建议在低峰期执行,并提前通知下游使用方。

案例与场景:一次典型的补数事故

某团队每天凌晨 2 点运行报表 DAG,依赖上游订单表。某次上游因故障延迟到 4 点才产出,但报表 DAG 没有数据依赖,2 点照常运行,结果当天报表为空。运维人员发现后直接回填当天数据,却因为任务非幂等,导致订单金额被重复累加,报表数值翻倍。最终不得不手动清理分区并重新计算。

这个案例暴露了三个问题:缺少数据依赖、任务非幂等、回填前未验证。如果上游就绪后再触发下游,如果写入前先清理目标分区,如果回填前先跑一天验证,这次事故完全可以避免。

误区与复盘

  • 误区一:把执行时间当数据时间。 逻辑日期才是数据区间的标识,回填时必须按逻辑日期操作。
  • 误区二:认为传感器越多越安全。 过多传感器会占用 worker 槽位,增加超时和死锁风险,应优先使用数据集触发或事件驱动。
  • 误区三:回填就是重跑。 回填涉及依赖重算、并发控制和幂等保证,不是简单点击“重跑”。
  • 误区四:忽略下游影响。 回填可能触发下游 DAG 或覆盖下游数据,必须评估影响范围。

在生产环境执行大规模回填前,务必确认:任务是否幂等、依赖是否会误触发、并发限制是否合理、是否有监控和回滚方案。缺少任何一项,都可能把一次补数变成一次事故。

实战环境准备

为了跟随后续章节实操,建议准备以下环境:

  • Airflow 2.7 及以上版本(支持 Dataset 触发与较完善的回填 CLI)。
  • 本地或容器化的元数据库(PostgreSQL 推荐),避免使用 SQLite 进行并发回填测试。
  • 一个可写的对象存储或数据库分区表,用于验证幂等写入。
  • 基础命令行工具:airflow、python、docker(可选)。
# 快速检查 Airflow 环境
airflow version
airflow dags list
airflow tasks list example_dag

当你能够清晰回答“这个任务处理的是哪段数据、它依赖什么条件、重跑是否安全”这三个问题时,就已经具备了进入后续实战章节的基础。接下来,我们将从逻辑日期与数据区间的精确建模开始,逐步构建可依赖、可回填、可验证的 Airflow 数据管道。