3、调度系统选型与配置:Airflow、Dagster、Prefect的核心概念与对比
调度系统,说白了就是数据流水线的「大脑」。它决定你的任务什么时候跑、怎么跑、跑失败了怎么办。我见过不少团队,代码写得挺好,结果选了个不合适的调度器,天天半夜被报警吵醒。
今天咱们聊聊三个主流选手:Airflow、Dagster 和 Prefect。它们都能调度任务,但设计哲学差挺多的。我会结合自己踩过的坑,帮你理清选型思路。
3.1 Airflow:老牌劲旅,生态为王
Airflow 是调度界的「Linux」。2015 年 Airbnb 开源,现在已经是 Apache 顶级项目。我最早接触调度系统就是它,那时候版本才 1.8。
它的核心概念其实不多:
- DAG:一个有向无环图,定义任务依赖关系。
- Task:DAG 里的一个节点,代表一个执行单元。
- Operator:任务的「模板」。比如 BashOperator 跑 shell 脚本,PythonOperator 跑 Python 函数。
- Scheduler:核心调度器,负责解析 DAG、触发任务。
- Executor:执行器,决定任务跑在哪个进程/机器上。
个人经验:Airflow 最大的优势是社区生态。你几乎能找到所有数据工具的 Operator:Spark、Hive、Kubernetes、AWS、GCP…… 我当年搭数据平台,80% 的集成工作直接复用社区代码,省了不少事。
但 Airflow 也有痛点。最明显的是 「调度延迟」——当 DAG 数量超过几百个,Scheduler 的解析压力会很大。我记得有一次线上 500 多个 DAG,调度周期从 30 秒拖到 5 分钟,排查了半天才发现是数据库连接池没配好。
避坑指南:我曾经在生产环境遇到过 DAG 解析超时。后来强制要求每个 DAG 文件不要超过 200 行,import 只加载必要的模块。另外,max_active_runs_per_dag 这个参数一定要设,不然并发跑起来能把数据库打爆。
3.2 Dagster:数据资产驱动的新思路
Dagster 是后起之秀,2019 年才开源。它的设计理念跟 Airflow 不太一样——不把调度当核心,而是把「数据资产」放在第一位。
你想想看,传统调度器只关心「任务跑没跑完」,但 Dagster 会问:「这个任务产出的数据表,下游谁在用?数据质量合格吗?」
核心概念:
- Asset:数据资产,比如一张表、一个文件。这是 Dagster 的一等公民。
- Op:计算单元,类似 Airflow 的 Task。
- Graph:多个 Op 组合成有向图。
- Job:一个可执行的作业,包含 Graph 和调度配置。
- Dagit:Web UI,可观测性做得特别好。
举个例子,定义一个数据资产:
from dagster import asset
@asset
def raw_orders(context):
"""从 API 拉取原始订单数据"""
data = fetch_orders_from_api()
context.log.info(f"拉取了 {len(data)} 条订单")
return data
@asset
def cleaned_orders(raw_orders):
"""清洗订单数据"""
return raw_orders.dropna()
看到没?你直接声明「我要产出 raw_orders 这个资产」,Dagster 会自动推导依赖关系。这在数据湖场景下特别爽——数据血缘清晰可见。
注意:Dagster 的学习曲线比 Airflow 陡。它的概念层更多(Asset、Op、Graph、Job、Schedule、Sensor……),团队如果全是 Airflow 老手,切换成本不低。我建议新项目可以考虑,但存量迁移要谨慎。
3.3 Prefect:开发体验至上的现代调度器
Prefect 的口号是「Pythonic 的调度器」。它的设计目标很明确:让数据工程师写调度代码像写普通 Python 一样自然。
核心概念:
- Flow:一个完整的流程,类似 DAG。
- Task:流程里的一个步骤。
- Deployment:把 Flow 部署到 Prefect Server 的配置。
- Orion Server:调度服务端(Prefect 2.x 版本)。
- Agent:执行任务的 worker。
Prefect 最让我喜欢的是 「动态流程」。什么意思?Airflow 的 DAG 必须在解析时确定结构,但 Prefect 允许你在运行时动态生成任务。比如:
from prefect import flow, task
@task
def process_file(filename: str):
# 处理单个文件
pass
@flow
def batch_process(file_list: list):
# 动态创建任务
for f in file_list:
process_file(f)
这在处理「不确定数量的输入文件」时特别有用。Airflow 要实现类似效果,得用 Dynamic Task Mapping(2.3 之后才支持),而且限制不少。
个人感受:Prefect 的本地开发体验是最好的。你可以在 Jupyter Notebook 里直接跑 Flow,调试完再部署。我有个同事用 Prefect 搭了个实时特征工程管道,从开发到上线只花了两天。
3.4 核心对比:一张表说清楚
| 维度 | Airflow | Dagster | Prefect |
|---|---|---|---|
| 设计哲学 | 调度优先 | 数据资产驱动 | 开发体验优先 |
| 核心抽象 | DAG / Task / Operator | Asset / Op / Graph / Job | Flow / Task / Deployment |
| 动态流程 | 有限(2.3+ 支持) | 中等(通过动态 Op) | 原生支持 |
| 数据血缘 | 需额外配置(Lineage Backend) | 内置,强血缘 | 内置,中等 |
| 可观测性 | 中等(依赖插件) | 强(Dagit UI) | 强(Prefect UI) |
| 社区生态 | 最成熟,Operator 丰富 | 成长中,集成较少 | 成长中,集成中等 |
| 运维复杂度 | 高(需管理 Scheduler + DB + Executor) | 中(Daemon + DB) | 低(Server + Agent 轻量) |
| 学习曲线 | 中 | 中高 | 低 |
| 适用场景 | 大型企业、复杂依赖、多系统集成 | 数据湖/数据中台、强数据治理需求 | 中小团队、快速迭代、动态流程 |
3.5 选型建议:别跟风,看场景
说实话,没有「最好」的调度器,只有「最合适」的。我见过用 Airflow 管 2000 个 DAG 跑得飞起的团队,也见过用 Prefect 做原型验证结果上线就崩的案例。
我的建议是:
- 团队规模大、系统复杂、需要稳定生态 → 选 Airflow。别犹豫,它经得起考验。
- 数据治理要求高、想做数据资产化管理 → 选 Dagster。它的血缘和可观测性是真的强。
- 团队小、迭代快、流程动态变化多 → 选 Prefect。开发效率能提升一大截。
一个小技巧:不管选哪个,先把「失败重试」「告警通知」「资源隔离」这三个基础能力配好。我见过太多团队,调度器选得花里胡哨,结果任务失败了没人知道,数据延迟了一整天。