返回 AI 资讯
数据流水线总是半夜崩?Airflow 把「定时任务」变成了可观测的工程
工作流2026-09-30风险:低

数据流水线总是半夜崩?Airflow 把「定时任务」变成了可观测的工程

一堆 crontab 散落各处、崩了不知道跑到第几步、重跑要从头来——这是数据流水线最常见的困境。这篇讲清楚 Airflow 是什么、为什么值得上、五分钟怎么跑起来,以及哪些情况其实不该用它。

定时任务跑到一半崩了,日志只留下一句 traceback,你不知道它跑到第几步、要不要从头再来。这是很多人维护数据流水线最熟悉的噩梦。

更常见的场景是:一堆 crontab 散落在几台机器上,谁依赖谁全靠人脑记。上游数据延迟了,下游照跑不误,跑出一堆脏数据,第二天业务方来问你才发现。

Apache Airflow 解决的就是这一类问题。它在 GitHub 上有 4.7 万 star,Apache-2.0 协议,商用完全没问题。这篇把它讲清楚:它到底是什么、为什么值得上、怎么最快跑起来,以及哪些情况其实不该用它。

官方项目页面截图
▲ 官方项目页面截图

它到底是什么

一句话:Airflow 是一个用 Python 代码来编写、调度和监控工作流的平台。

关键词是"用代码"。你的工作流不是在某个网页上点出来的,而是一个 Python 文件,里面有任务、有依赖关系。这件事带来的好处是决定性的——工作流可以进 Git、可以 code review、可以做版本管理、可以用 CI 跑测试。运维同学最怕的"配置漂移",在 Airflow 里从根上被掐掉了。

Airflow 里有两个必须分清的概念:

  • DAG(有向无环图):描述"哪些任务、谁先谁后"。一个 DAG 就是一个工作流。
  • Task:DAG 里的一个具体步骤,比如跑一段 SQL、调一个接口、搬一个文件。

DAG 定义的是结构,不是数据。任务之间传递少量元数据,大数据量走外部存储。理解这一点,能帮你避开后面很多坑。

为什么不用 crontab

很多人第一反应是"我用 cron 也能定时跑"。能跑,但缺的东西太多:

  • 依赖管理:cron 不知道 B 要等 A 跑完,你只能靠"预估 A 要 10 分钟,那 B 定在 10 分钟后"这种脆弱的约定
  • 失败重试:cron 崩了就是崩了,没有自动重试,更没有指数退避
  • 回溯补数:上游修好了要重跑过去 7 天的数据,cron 得你手动一天天点
  • 可观测性:谁在跑、跑了多久、哪一步慢了,cron 一概不知
  • 告警:失败了谁能第一时间知道

Airflow 把这些全做成了内置能力。更关键的是回填(backfill):你指定一个时间区间,它自动把这段时间缺失的任务补跑一遍,而且保证幂等。这一条在数据场景里能救命。

五分钟跑起来

最快的方式是 Docker。官方提供了 compose 文件,几步就能起一个能用的环境。

一个最小可用的 DAG 长这样:

from airflow import DAG

from airflow.operators.bash import BashOperator

from datetime import datetime

with DAG(

dag_id="daily_report",

start_date=datetime(2026, 1, 1),

schedule="@daily",

catchup=False,

) as dag:

extract = BashOperator(

task_id="extract",

bash_command="python /opt/scripts/extract.py",

)

load = BashOperator(

task_id="load",

bash_command="python /opt/scripts/load.py",

)

extract >> load

最后那行 extract >> load 就是在声明依赖:extract 跑完才跑 load。你也可以用 <<,或者列表形式声明多个依赖。

把文件丢进 dags/ 目录,Airflow 会自动加载,Web UI 里立刻能看到。改一行代码、刷新页面、看到依赖图变了——这个反馈循环非常快,是 Airflow 上手体验最好的部分。

上手要理解的三个机制

调度时间不等于执行时间。 这是新人最常踩的坑。Airflow 的 DAG 有一个"数据区间"的概念:@daily 的任务,在 1 月 2 日凌晨跑的那次,处理的是 1 月 1 日的数据区间。它不是"到点就跑",而是"到点了,该处理上一区间的数据了"。想明白了这一点,execution_date 的很多诡异行为就都能解释了。

幂等性要自己保证。 Airflow 会重试、会回填,意味着同一个任务可能被执行多次。如果你的任务不是幂等的(跑两次结果不一样,或者产生重复数据),重跑就是灾难。正确做法是让任务写入时用"覆盖分区"而不是"追加"。

Executor 决定能跑多大。 默认的 executor 只适合开发调试。生产环境你需要在 Celery Executor 和 Kubernetes Executor 之间选:前者靠一组常驻 worker,后者每个任务开一个 Pod。任务多、资源需求差异大的选 K8s;稳定、量大、追求吞吐的选 Celery。

什么人适合上,什么情况先别急

适合的:

  • 有明确的批处理流水线,任务之间有依赖关系
  • 需要回溯补数、失败自动重试
  • 团队希望流水线能被 code review、能进版本控制
  • 数据量在"单机跑不动、上 Spark 又太重"这个区间

先别急的:

  • 实时流处理。Airflow 是批处理调度器,不是流引擎,秒级延迟的需求请找 Flink 这类
  • 只有两三个独立脚本。为三个定时任务上一套 Airflow,运维成本远超收益
  • 任务里要传大数据。Airflow 的 XCom 是给元数据用的,把 DataFrame 塞进去会直接把元数据库压垮

生产环境必须做的四件事

元数据库换成 Postgres 或 MySQL。 Airflow 默认的 SQLite 只支持单线程,生产上会直接锁死。这个改动要在上量之前做,之后迁移会比较麻烦。

把 DAG 解析和执行分开。 DAG 文件会被调度器周期性解析,如果解析逻辑里放了重型操作(比如查数据库、读大文件),会拖垮整个调度器。原则:DAG 文件只定义结构,重活放进 Task 里。

资源隔离用 Pool。 不同 DAG 之间会争抢 worker 资源。用 Pool 给关键流水线预留槽位,避免一个不重要的大任务把核心报表的资源吃光。这是多团队共用一套 Airflow 时的必备配置。

日志要外挂。 默认日志存在本地,容器一重启就没了。配远程日志(S3、GCS 或 NFS),出事之后你才有东西可查——排查问题时最有价值的往往就是那几行日志。

排查问题的三个常用入口

任务失败时不要只看最后一行的报错。三个地方按这个顺序查:

1. Task 实例的日志:Web UI 里点进具体任务看完整日志,这是最直接的

2. 调度器日志:如果 DAG 压根没被调度,问题在调度器侧(常见原因是 DAG 文件有语法错误)

3. 元数据库的 dag_run 表:看这次运行的状态是什么、卡在哪一步

一个经验规律:任务根本没启动,八成是依赖没满足或者 DAG 解析失败;任务启动了但失败,才是代码本身的问题。

真实建议

如果你现在有一堆散落的 cron,最务实的迁移路径不是一次性全搬。挑一条最痛的流水线——就是那个"崩了要人工介入、还得从头跑"的——先把它改成 DAG。等你在 Web UI 里第一次看到"哪一步慢了 40 分钟"这个信息,你会立刻明白这套东西值不值。

官方仓库和完整文档在 github.com/apache/airflow。

适合谁:维护批处理任务的后端/数据工程师、需要回溯补数的团队、想把流水线纳入版本控制的工程团队

相关资讯