catchup 是什么
catchup 决定一个 DAG 上线时要不要「补历史」:开启后调度器会从 start_date 起把每个调度周期都生成一次运行,一直追到当前;关闭则只从上线之后的时间点开始跑。这个开关看起来只是个小参数,但它决定了上线瞬间会给集群带来多少任务——start_date 写成年初、周期是每天、又开了 catchup,等于一次性放出几百个 DagRun。
基本信息
| catchup=True | 补齐 start_date 以来的每个调度周期 |
|---|---|
| catchup=False | 跳过历史,只跑当前及之后 |
| 配套参数 | max_active_runs 限制同时运行的周期数 |
| 适用建议 | 历史数据无需回刷时关闭;需要补历史时用受控的 backfill |
| 影响范围 | 仅对新上线的 DAG 或修改 restart_date 后生效 |
| 版本差异 | Airflow 2.x 用 catchup 参数,3.x 中改名后有对应设置 |
Airflow DAG 参数
Airflow DAG 参数
from datetime import datetime
from airflow import DAG
dag = DAG(
'daily_orders',
start_date=datetime(2026, 1, 1),
schedule='0 2 * * *',
catchup=False, # 上线后不补历史
max_active_runs=1, # 同时只允许一个周期在跑
default_args={'retries': 2},
)典型使用场景
- 新 DAG 首次上线:确认历史已由离线任务补过,用 catchup=False 直接接当天
- 需要追历史:保留 catchup 但先把 max_active_runs 设为 1,观察资源后再放开
- 上线演练:在测试环境打开 catchup 看任务密度,再决定生产配置
- 误开排查:发现集群突然多出大量 DagRun,先确认是不是某个新 DAG 开了 catchup
- 口径重刷:不用 catchup 全量追,改用 backfill 指定区间分批重跑
- 关闭后的验证:上线当天手动触发一次运行,确认调度周期与分区口径符合预期
参数组合影响
| catchup | max_active_runs | 结果 |
|---|---|---|
| True | 未限制 | 瞬间生成大量周期,抢占 worker |
| True | 1 | 按周期串行追平,资源可控但耗时长 |
| False | 任意 | 跳过历史,只跑之后的时间点 |
| False + backfill | 由命令控制 | 按指定区间受控补数 |
开启 catchup 且 start_date 很早时会瞬间创建成百上千个 DagRun,要配合 max_active_runs 与并发限制。
catchup 只在 DAG 首次被调度器感知时起作用;已经跑过的 DAG 改这个参数不会重新生成历史周期,需要补历史仍要走 backfill。
把 start_date 写在 DAG 文件里而不是每个任务里,避免同一 DAG 内不同任务计算出的周期不一致。