初识 Prefect:为什么我放弃了 Airflow
先说说我的经历吧。2019 年我刚接手一个数据管道项目,团队用的是 Airflow。每天光 DAG 解析失败就要花半小时排查,调度器动不动就卡死。后来我偶然翻到了 Prefect 的文档,试用了一周就决定全量迁移。嗯,这个决定让我少加了半年班。
Prefect 是什么?说白了,它是一个 Python 原生的工作流编排框架。你写几个函数,加个装饰器,就能搭出一条生产级的数据管道。它不要求你学 XML、YAML 或者什么 DSL,你写的代码就是工作流本身。
一句话总结:Prefect = Python 函数 + 装饰器 + 自动重试 + 可视化 UI。它让工作流编排变得像写普通脚本一样自然。
为什么选择 Prefect?
我选工具的标准很简单:上手快、不出错、好排查。Prefect 在这三点上都做得不错。
- Python 原生——你不需要学第二套配置语言。写个
@flow和@task就完事了。 - 自动重试与状态管理——任务失败后自动重试,状态持久化到数据库,挂了也不丢进度。
- 开箱即用的 UI——不用搭 Grafana、不用写 PromQL,Prefect Server 自带仪表盘,运行历史、日志、任务图全都有。
- 本地开发友好——你可以在 Jupyter Notebook 里调试 flow,跑通了再部署到生产。
我的习惯:新项目我总会先搭一个 Prefect 本地环境,写三个 task 串起来跑一遍。能跑通,再考虑 Docker 化。这个流程帮我筛掉了不少配置问题。
Prefect vs Airflow:一张表说清楚
很多人问我:有 Airflow 为什么还要用 Prefect?我直接拿项目里的真实对比给你看。
| 对比维度 | Airflow | Prefect |
|---|---|---|
| 定义方式 | DAG 文件 + Python 运算符 | Python 装饰器(@flow / @task) |
| 调度器 | 单点,容易成为瓶颈 | 无中心调度器,任务直接提交 |
| 重试机制 | 需手动配置 retries | 默认自动重试,可配置指数退避 |
| 状态持久化 | 依赖数据库轮询 | 事件驱动,状态实时写入 |
| 本地调试 | 需要启动全套服务 | 单进程即可运行 |
| 学习曲线 | 中等(需理解运算符、钩子、池等概念) | 低(会写函数就会用) |
你看,Airflow 更像一个重型框架,适合大团队统一管控。Prefect 则轻巧得多,适合快速迭代的团队。我个人建议:团队小于 10 人、项目迭代快、不想在基础设施上花太多时间,直接上 Prefect。
避坑指南:我曾经在一个项目里强行用 Airflow 做实时流处理,结果调度器每 30 秒轮询一次,数据库连接数直接打满。后来换成 Prefect 的事件驱动模式,连接数降了 80%。选工具一定要看场景,别盲目追大厂方案。
核心概念速览
Prefect 的核心概念其实就四个,你花十分钟就能理解。
- Flow——工作流的容器。你可以把它理解成一个函数,里面编排了多个任务。
- Task——工作流里的最小执行单元。每个 task 就是一个 Python 函数,加上
@task装饰器。 - State——任务或流程的状态。比如 Pending、Running、Success、Failed。Prefect 会把状态持久化,方便你回溯。
- Runner——执行引擎。它负责调度 task、处理依赖、管理重试。
下面这张图展示了它们之间的关系:
你想想看,一个 Flow 里可以串行、并行、甚至条件分支。每个 Task 独立运行,互不干扰。如果 Task B 失败了,Prefect 会自动重试,或者根据你的配置跳过、暂停整个 Flow。这种灵活性在实际项目中太重要了。
我的建议:刚开始学 Prefect,别急着搭集群。先在本机装个 prefect 包,写一个包含三个 task 的 flow,跑通它。你会在 10 分钟内理解 80% 的核心概念。
一个最小示例
光说不练假把式。下面这个例子,你复制到本地就能跑。
from prefect import flow, task
@task
def fetch_data():
return [1, 2, 3, 4, 5]
@task
def compute_sum(data):
return sum(data)
@task
def print_result(result):
print(f"计算结果: {result}")
@flow
def my_first_flow():
data = fetch_data()
total = compute_sum(data)
print_result(total)
if __name__ == "__main__":
my_first_flow()
运行后你会看到控制台输出 计算结果: 15。就这么简单。你不需要写 DAG 文件,不需要启动调度器,一个 Python 文件搞定一切。
注意:如果你在 Jupyter Notebook 里运行,记得先执行 prefect config set PREFECT_ORION_DATABASE_CONNECTION_URL="sqlite:///./prefect.db",否则状态不会持久化。我刚开始就踩了这个坑,跑了半天发现历史记录全丢了。