开源项目第177期:Apache Airflow — 用 Python 写出来的工作流调度器,数据工程师的标配工具

316 阅读10分钟

引言

"如果你的代码需要按顺序执行、需要定时触发、需要处理失败重试,你就需要一个调度器。"

这是「每日一个开源项目」系列的第 177 篇。今天的项目是 Apache Airflow —— 用 Python 编写和调度工作流的平台,数据工程领域最广泛使用的开源工具之一。

在谈技术之前,先回答一个问题:Airflow 到底能做什么?

简单说:任何需要"按顺序执行多个步骤,步骤之间有依赖关系,需要定时或按条件触发"的工作,都可以用 Airflow 管理。 最典型的是数据管道——每天凌晨从数据库拉数据、清洗、写入数据仓库、生成报表。但它不止于此:训练机器学习模型、发送邮件报告、自动化基础设施操作,都有真实的生产用例。

46,400 颗 Star,Apache 2.0,版本 3.3.0,全球数千家公司在生产环境使用。

你会学到什么

  • Airflow 能解决哪四类核心问题(重点)
  • DAG 是什么,为什么用图来描述工作流
  • Operator 和 Provider:600+ 内置集成覆盖哪些系统
  • Airflow 3.0 的关键新特性:事件驱动调度和 Asset 感知
  • 快速上手:用 10 行 Python 写一个真实 DAG
  • 什么时候该用 Airflow,什么时候不该用

前提知识

  • 会写基础 Python
  • 了解"定时任务"的概念(cron 等)
  • 对数据处理流程有基本认知(不需要是专业数据工程师)

Airflow 能做什么(核心问题)

这是本文最重要的部分。

场景一:ETL/ELT 数据管道

最主要的用途。 数据工程师每天面对的典型问题:

每天凌晨 2 点:
  1. 从 MySQL 业务数据库拉取昨天的订单数据
  2. 清洗和转换(去重、格式标准化、补充维度数据)
  3. 写入 BigQuery / Snowflake 数据仓库
  4. 更新 BI 报表
  5. 如果第 3 步失败,发 Slack 告警并重试

这 5 步有严格的执行顺序,步骤 4 必须在步骤 3 成功后才能运行。

Airflow 把这个流程写成一个 DAG,配置好依赖关系,每天自动触发,每步失败都有记录,重试逻辑可配置,所有历史执行都在 Web UI 里可查。

真实规模:Airbnb(Airflow 的创始公司)最初用它管理每天数百个 ETL 任务。现在有公司在生产环境跑几千个 DAG,每天执行数十万个任务。

场景二:机器学习训练流水线

MLOps 场景越来越普遍:

每周一:
  1. 从数据仓库拉取最新训练数据
  2. 特征工程(归一化、编码、拆分训练/测试集)
  3. 训练模型(可以是 Python 脚本、也可以提交到 Spark 集群)
  4. 评估模型指标(精确率、召回率、AUC)
  5. 如果指标超过阈值,自动部署到生产环境
  6. 如果低于阈值,通知数据科学团队

步骤 5 和 6 是条件分支——Airflow 的 BranchPythonOperator 支持基于上一步结果做不同处理。

场景三:定时报表和数据同步

不需要是复杂的大数据场景:

  • 每天早上 9 点把昨天的销售数据发给管理层(邮件 + Excel 附件)
  • 每小时把 CRM 里的新客户数据同步到营销平台
  • 每周五把各部门的 KPI 汇总后写入 Google Sheets
  • 每月 1 号生成上月财务报表并上传 S3

这些工作以前靠 cron + shell 脚本处理,Airflow 提供了可观察性:每次执行成不成功、哪步慢了、失败后怎么处理,一目了然。

场景四:基础设施自动化

Airflow 不限于数据场景:

  • 每天检测 S3 里超过 30 天的文件并归档压缩
  • 生产环境数据库的定时备份和备份验证
  • 自动化的云资源扩缩容(高峰期扩、低谷期缩)
  • CI/CD 管道中的集成测试编排

核心概念:DAG

为什么用"图"来描述工作流

DAG = Directed Acyclic Graph,有向无环图。每个节点是一个任务(Task),节点之间的边表示"必须先完成 A,才能开始 B"的依赖关系。"无环"确保不会出现死锁(A 等 B,B 等 A)。

一个典型的 DAG(数据管道):

extract_data ──→ transform_data ──→ load_to_warehouse ──→ send_report
                      ↓
              validate_schema ──→ quarantine_bad_data

Airflow 用 Python 定义这个图:

from airflow import DAG
from airflow.operators.python import PythonOperator
from airflow.operators.bash import BashOperator
from datetime import datetime, timedelta

# DAG 定义
with DAG(
    dag_id="daily_sales_pipeline",
    schedule="0 2 * * *",       # 每天凌晨 2 点
    start_date=datetime(2026, 1, 1),
    catchup=False,
    default_args={
        "retries": 2,
        "retry_delay": timedelta(minutes=5),
    },
) as dag:

    # 任务 1:从数据库提取数据
    extract = PythonOperator(
        task_id="extract_data",
        python_callable=extract_from_mysql,
    )

    # 任务 2:数据转换和清洗
    transform = PythonOperator(
        task_id="transform_data",
        python_callable=clean_and_transform,
    )

    # 任务 3:写入数据仓库
    load = PythonOperator(
        task_id="load_to_warehouse",
        python_callable=load_to_bigquery,
    )

    # 任务 4:发送报告
    report = BashOperator(
        task_id="send_report",
        bash_command="python send_email.py --date {{ ds }}",
    )

    # 定义依赖关系(执行顺序)
    extract >> transform >> load >> report

这 40 行 Python 就是一个完整的生产数据管道。Airflow 负责在凌晨 2 点触发它,按顺序执行每个任务,失败时重试,在 Web UI 里展示每次运行的状态。

调度方式

Airflow 支持多种触发方式:

# 定时调度(标准 cron 表达式)
schedule="0 9 * * 1-5"   # 工作日早上 9 点

# Airflow 内置快捷方式
schedule="@daily"          # 每天
schedule="@hourly"         # 每小时
schedule="@weekly"         # 每周

# 3.0 新增:Asset 事件触发(数据驱动调度)
from airflow.sdk import Asset
schedule=Asset("s3://my-bucket/raw-data/")  # 当这个数据集更新时触发

参数化和动态 DAG

因为 DAG 是 Python 代码,可以用 Python 的全部能力动态生成:

# 用循环为 10 个地区各生成一个相同结构的任务
for region in ["us-east", "eu-west", "ap-south", ...]:
    PythonOperator(
        task_id=f"process_{region}",
        python_callable=process_region,
        op_kwargs={"region": region},
    )

Operator 和 Provider:600+ 内置集成

Operator 是 Airflow 的"任务模板"——每种 Operator 封装了与特定系统交互的逻辑。

内置 Operator(无需额外安装)

Operator用途
PythonOperator执行任意 Python 函数
BashOperator执行 Shell 命令
BranchPythonOperator根据条件选择执行分支
EmailOperator发送邮件
HttpOperator调用 HTTP API
TriggerDagRunOperator触发另一个 DAG
ShortCircuitOperator条件不满足时跳过后续任务

Provider 包(按需安装)

Provider 是针对特定平台的 Operator 集合,pip install apache-airflow-providers-XXX 安装:

云服务

  • aws — S3、Redshift、EMR、Lambda、Glue、SageMaker
  • google — BigQuery、GCS、Dataflow、Vertex AI、Pub/Sub
  • azure — Blob Storage、Data Lake、Synapse、Azure ML

数据库

  • postgres、mysql、snowflake、databricks、spark

消息队列

  • apache-kafka、rabbitmq、redis

其他工具

  • slack、github、http、ssh、docker、kubernetes

实际写一个从 S3 读数据写入 BigQuery 的任务:

from airflow.providers.amazon.aws.operators.s3 import S3FileTransformOperator
from airflow.providers.google.cloud.transfers.s3_to_gcs import S3ToGCSOperator
from airflow.providers.google.cloud.operators.bigquery import BigQueryInsertJobOperator

# S3 数据 → Google Cloud Storage → BigQuery
s3_to_gcs = S3ToGCSOperator(
    task_id="s3_to_gcs",
    bucket="my-s3-bucket",
    prefix="data/2026-08-03/",
    dest_gcs="gs://my-gcs-bucket/",
)

bq_load = BigQueryInsertJobOperator(
    task_id="load_to_bq",
    configuration={
        "load": {
            "sourceUris": ["gs://my-gcs-bucket/data/*"],
            "destinationTable": {
                "projectId": "my-project",
                "datasetId": "sales",
                "tableId": "daily_orders",
            },
        }
    },
)

s3_to_gcs >> bq_load

Airflow 3.0 的关键变化

Airflow 3.0 于 2025 年发布,两个最重要的新特性:

事件驱动调度(Asset Watchers)

3.0 之前,Airflow 主要靠 cron 定时触发——每天固定时间跑,不管数据是否已经准备好。

3.0 引入了 Asset(数据资产)概念:DAG 可以"订阅"一个数据资产,当这个资产更新时自动触发,而不是等固定时间。

from airflow.sdk import Asset, DAG

# 定义一个数据资产
raw_orders = Asset("s3://data-lake/raw/orders/")

# 这个 DAG 在 raw_orders 数据集更新时触发
with DAG(
    dag_id="process_orders",
    schedule=raw_orders,   # 数据驱动,不是时间驱动
):
    ...

还支持 Asset Watcher,持续监听消息队列(Kafka、SQS 等),实现近实时的事件驱动:

from airflow.providers.standard.asset.watchers import KafkaAssetWatcher

my_asset = Asset(
    "orders-stream",
    watchers=[KafkaAssetWatcher(topic="new-orders", ...)],
)

DAG 版本控制

3.0 给每个 DAG 增加了版本号。修改 DAG 代码后,旧的历史运行记录保留原版本快照,新的运行使用新版本。这解决了一个长期痛点:以前修改 DAG 会导致历史记录对不上。


Web UI:可视化监控

Airflow 的 Web UI 是它的核心卖点之一。启动后在浏览器里能看到:

Grid 视图:每个 DAG 每次运行的所有任务状态,按时间从左到右排列,绿色=成功,红色=失败,黄色=运行中。一眼看出哪个时间段出了问题。

Graph 视图:DAG 的有向图,节点颜色反映当前运行状态,点击节点可以看日志、重新运行单个任务、查看执行时间。

Assets 视图(3.0 新增):数据资产的依赖关系图,展示哪些 DAG 生产数据、哪些 DAG 消费数据。


快速开始

安装(最简单方式)

# 创建虚拟环境
python -m venv airflow-env
source airflow-env/bin/activate

# 安装 Airflow(约束文件确保依赖版本兼容)
AIRFLOW_VERSION=3.3.0
PYTHON_VERSION=3.12
CONSTRAINT_URL="https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-${PYTHON_VERSION}.txt"
pip install "apache-airflow==${AIRFLOW_VERSION}" --constraint "${CONSTRAINT_URL}"

# 初始化数据库并启动(开发用,单机模式)
airflow standalone

浏览器打开 http://localhost:8080,用 admin/admin 登录。

生产部署

生产环境推荐用官方 Helm chart 部署到 Kubernetes:

helm repo add apache-airflow https://airflow.apache.org
helm install airflow apache-airflow/airflow \
  --namespace airflow \
  --create-namespace

或使用托管服务:Astronomer(商业托管)、Amazon MWAA、Google Cloud Composer。


什么时候该用,什么时候不该用

适合 Airflow 的场景

  • 批处理工作流:步骤之间有明确依赖,需要定时或按事件触发
  • 需要可观察性:哪次失败了、哪步慢了、要能回溯历史
  • 多系统集成:数据在 MySQL → Spark → S3 → Snowflake 之间流动
  • 团队协作:多个数据工程师共同维护大量管道

不适合 Airflow 的场景

  • 流处理:需要毫秒级延迟的实时流处理,用 Kafka Streams 或 Flink
  • 简单 cron 任务:只是定时执行一个脚本,crontab 就够了,不需要引入 Airflow
  • 纯 API 服务:Airflow 是调度器,不是 Web 框架
  • 极短间隔触发:每秒触发的任务不适合 Airflow,它的调度粒度是分钟级

项目地址与资源


总结

Airflow 解决的问题用一句话概括:把"一串有依赖关系的任务"从手工维护的脚本,变成可以定时触发、失败自动重试、执行历史可查、团队共同维护的工程化工作流。

它的核心价值不是"帮你执行任务",而是"管理任务之间的关系"——谁先谁后、谁依赖谁、失败了怎么办、成功后通知谁、数据准备好了自动触发。

Airflow 3.0 把触发方式从"定时"扩展到"数据就绪",让整个管道从时间驱动变成事件驱动。这对数据仓库场景的意义很大:不再需要在凌晨 2 点固定等待上游数据,而是上游数据一到,下游任务立刻开始。

46,000 颗 Star,17 年的积累,生产环境跑了十年的验证——如果你的工作涉及数据管道、定时任务或多步骤自动化,Airflow 是目前社区最成熟的选择。


探索 PrimeSkills —— 精选 AI Agent 与技能的市场,每一个都经过真实企业工作流验证,去掉浮夸,留下真正有用的。

欢迎访问我的个人主页,发现更多有价值的见解和有趣的产品。