Django 6.0 自带 Tasks 到底能不能替代 Celery?跑完 3 组后台任务后我有答案了

Django 6.0 自带 Tasks 到底能不能替代 Celery?跑完 3 组后台任务后我有答案了

Django 6.0 第一次把 Tasks 框架放进了核心。看到 @taskenqueue()、队列名、优先级和任务结果这些 API,很多人的第一反应都是:以后 Django 项目是不是可以删掉 Celery 了?

我没有只看发布说明,而是在隔离环境中安装 Django 6.0.7、Celery 5.6.3,并连接本机 Redis,真实运行了三组 1.5 秒任务:

  1. 普通同步函数;
  2. Django 自带的 ImmediateBackendDummyBackend
  3. Redis + 独立 Celery Worker。

先给结论:Django Tasks 不能单独替代 Celery。它统一了"如何声明和提交任务",但不提供生产可用的消息队列与 Worker。Celery 解决的是任务如何被可靠地搬运、执行、重试和监控。

这两者不是简单的新旧替代关系,而是位于不同层次。

Django 6.0 到底内置了什么

Django 官方对 Tasks 框架的定义非常克制:它提供后台工作的"contract and plumbing",也就是任务契约和连接管道,而真正执行任务的引擎留给外部基础设施。

最小任务可以这样定义:

python 复制代码
from django.tasks import task


@task
def generate_report(report_id):
    # 生成报表
    return {"report_id": report_id, "status": "done"}

调用时不是 Celery 的 delay(),而是 Django 自己的 enqueue()

python 复制代码
result = generate_report.enqueue(42)

Tasks API 还定义了这些通用概念:

  • priority:任务优先级;
  • queue_name:目标队列;
  • backend:使用哪个任务后端;
  • run_after:最早执行时间;
  • TaskResult:任务状态、尝试次数、错误与返回值;
  • enqueue() / aenqueue():同步与异步提交接口。

这很重要。过去每个任务库都有自己的装饰器、调用方法和结果对象;Django 6.0 开始提供框架级统一接口,让业务代码有机会减少对具体队列实现的直接依赖。

但统一接口不等于任务已经在后台执行。

两个自带 Backend 都不是生产 Worker

Django 6.0 自带两个后端。

ImmediateBackend:名字叫 Task,实际仍在当前进程执行

默认配置就是 ImmediateBackend

python 复制代码
TASKS = {
    "default": {
        "BACKEND": "django.tasks.backends.immediate.ImmediateBackend",
    }
}

它会在调用 enqueue() 时立刻执行任务。如果任务耗时 1.5 秒,请求仍然要等待 1.5 秒。

它适合:

  • 本地开发;
  • 单元测试;
  • 在真正的队列基础设施上线前,先改造业务调用接口。

它不具备把耗时工作移出 Web 请求进程的能力。

DummyBackend:返回得很快,因为它根本不执行

DummyBackend 会记录入队任务,方便测试检查,但不会执行任务函数:

python 复制代码
TASKS = {
    "default": {
        "BACKEND": "django.tasks.backends.dummy.DummyBackend",
    }
}

所以看到它在 1 ms 内返回,不能解释为"Django 后台任务性能惊人"。它只是把任务保存为测试记录,状态停留在 READY

官方文档也明确说明:Django 内置的只有开发和测试后端,生产可用后端需要额外配置。

实战步骤与验证结果

测试环境如下:

项目 配置
Python 3.12
Django 6.0.7
Celery 5.6.3
Broker Redis,本地独立数据库编号
Worker 单独进程,--pool=solo
任务内容 sleep(1.5) 模拟邮件、报表或文件处理
轮数 5 轮

测试任务故意返回执行进程 PID,用来判断它到底在 Web/请求进程里运行,还是被独立 Worker 接走。

第一组:普通同步函数

python 复制代码
def slow_job(delay_seconds):
    time.sleep(delay_seconds)
    return {"worker_pid": os.getpid()}

直接调用时,请求进程必须等待任务结束。

第二组:Django ImmediateBackend 与 DummyBackend

python 复制代码
from django.tasks import task


@task
def django_slow_job(delay_seconds):
    return slow_job(delay_seconds)


immediate_result = django_slow_job.enqueue(1.5)
dummy_result = django_slow_job.using(backend="dummy").enqueue(1.5)

ImmediateBackend 会真正执行;DummyBackend 只记录任务。

第三组:Redis + 独立 Celery Worker

Celery 任务如下:

python 复制代码
from celery import Celery

app = Celery(
    "django_tasks_demo",
    broker="redis://127.0.0.1:6379/13",
    backend="redis://127.0.0.1:6379/14",
)


@app.task
def celery_slow_job(delay_seconds):
    time.sleep(delay_seconds)
    return {"worker_pid": os.getpid()}

启动独立 Worker:

powershell 复制代码
python -m celery -A celery_app:app worker `
  --pool=solo `
  --queues=ruyi_django_tasks_demo

提交任务并记录入队返回时间:

python 复制代码
started = time.perf_counter()
result = celery_slow_job.delay(1.5)
enqueue_ms = (time.perf_counter() - started) * 1000

实验里调用 result.get() 只是为了确认 Worker 最终执行完成并记录总耗时。真实 Web 请求里通常不应在提交任务后立刻 get(),否则又会把异步流程等成同步流程。

五轮真实结果

方案 平均返回时间 最小值 最大值 是否执行 执行进程
同步函数 1500.29 ms 1500.18 ms 1500.54 ms 请求进程 PID 42268
Django ImmediateBackend 1500.66 ms 1500.39 ms 1501.24 ms 请求进程 PID 42268
Django DummyBackend 0.31 ms 0.16 ms 0.84 ms
Celery 入队返回 13.66 ms 0.68 ms 65.18 ms Worker PID 37412

Celery 任务的平均完整完成时间是 1515.71 ms。任务本身并没有被"加速":它仍然需要约 1.5 秒。真正改变的是 Web 请求只负责把消息送进队列,耗时工作由另一个进程完成。

这也是后台任务最关键的价值:不是让工作凭空变快,而是让请求线程不用陪它一起等。

首轮 Celery 入队时间较高,主要包含首次建立 Broker 连接的成本;后续轮次最低降到 0.68 ms。因此不能拿一次冷启动结果代表长期吞吐,也不能把这组本地数据直接当成生产性能承诺。

Django Tasks 和 Celery 的能力边界

能力 Django 6.0 Tasks 核心 Celery
统一任务声明与入队接口 有自己的 API
自带生产 Worker
自带生产消息传输 支持 Redis、RabbitMQ 等 Broker
重试、路由、并发控制 取决于外部 Backend 成熟支持
定时与复杂工作流 取决于外部 Backend Celery Beat、Canvas 等生态
测试时立即执行或只记录 内置支持 可用 eager 等配置
结果监控与运维工具 取决于 Backend 有成熟生态

所以"Django Tasks 能不能替代 Celery"需要拆成两个问题:

  1. 能不能替代 Celery 的业务调用接口? 有可能。使用兼容的生产 Backend 后,业务可以围绕 Django 的 @taskenqueue() 编写。
  2. 能不能替代 Celery 的队列、Worker 和运维能力? Django 核心本身不能。

新项目到底应该怎么选

选择 Django Tasks + 生产 Backend

适合这些情况:

  • 新建 Django 6.0 项目,希望先统一任务接口;
  • 任务模型简单,以发邮件、生成缩略图、轻量数据处理为主;
  • 已经验证某个外部 Backend 支持所需的延迟、优先级、结果查询和异步任务能力;
  • 希望未来更换任务实现时,尽量少改业务层。

不要只看 Backend 能否安装。Django Tasks 为后端定义了 supports_defersupports_prioritysupports_get_resultsupports_async_task 等能力标志,选型时应逐项核对。

继续使用 Celery

适合这些情况:

  • 现有系统已经稳定使用 Celery;
  • 需要任务重试、限流、路由、多队列、定时任务或复杂工作流;
  • 需要多台机器或多类 Worker;
  • 已有 Redis/RabbitMQ、监控和部署体系;
  • 团队已经积累 Celery 故障处理经验。

仅仅因为 Django 6.0 新增 Tasks,就把成熟 Celery 系统整体重写,通常没有收益。

三个最容易踩的坑

坑一:把 enqueue 当成一定异步

enqueue() 的真实行为由 Backend 决定。默认 ImmediateBackend 仍会阻塞当前调用者。

坑二:测试很快,就以为生产可用

DummyBackend 不执行任务;ImmediateBackend 不离开当前进程。两者都不能证明生产队列正常。

坑三:数据库事务还没提交,Worker 已经开跑

创建订单后立刻提交邮件任务时,Worker 可能早于数据库事务提交读取订单。通用做法是提交成功后再入队:

python 复制代码
from django.db import transaction

transaction.on_commit(lambda: generate_report.enqueue(report_id))

Celery 的 Django 集成也提供 delay_on_commit() 来处理这一常见场景。任务参数最好传主键等稳定标识,让 Worker 执行时重新读取最新数据,而不是直接序列化整个模型对象。

Windows 实验需要特别说明

本文为了在本机完成可重复验证,Celery Worker 使用了 --pool=solo。Celery 官方目前不承诺 Windows 支持,这个配置适合演示独立进程与消息队列链路,不代表生产部署建议。

生产环境通常应在 Linux 上根据任务类型评估 Worker 并发模型,并使用正式维护的 Redis 或 RabbitMQ 服务。

结论:Django Tasks 不能单独替代 Celery

Django 6.0 Tasks 最重要的意义,不是"Django 把 Celery 做进核心了",而是 Django 终于提供了一套框架级任务语言:

  • @task 声明任务;
  • enqueue() 提交任务;
  • 用 Backend 隔离具体执行设施;
  • 用统一的结果和能力模型描述任务状态。

但协议不会自己执行任务。没有生产 Backend、Broker 和 Worker,耗时工作仍然不会离开请求进程。

因此我的答案是:Django Tasks 可以降低业务代码对具体任务库的耦合,但它不能单独替代 Celery。对于已有复杂异步体系的项目继续用 Celery;对于 Django 6.0 新项目,可以优先采用 Tasks API,再认真选择生产 Backend。

参考资料

相关推荐
玉鸯1 小时前
Agent 的任务编排:从 System Prompt 到 Hierarchical Multi-Agent
python·llm·agent
我的xiaodoujiao1 小时前
快速学习Python基础知识详细图文教程14--模块
开发语言·python·学习·测试工具
残影飞雪1 小时前
Ollama对话脚本
python
jerryinwuhan1 小时前
数据预处理技术 2026-2027-1 开篇-课程介绍
大数据·python
看昭奚恤哭2 小时前
ontainer App】Container App无法从Container Registries 拉取镜像 - 报错 Forbidden
后端·python·flask
0566462 小时前
Python康复训练——数据结构
数据结构·windows·python
Tinyfacture2 小时前
接口自动化之添加商品(pytest)
python·测试工具·自动化·pytest
听雨入夜2 小时前
“同声传译”还是“全文翻译”?为何HotSpot虚拟机仍要保留解释器?
开发语言·python
随风M记忆s2 小时前
GEE&Python-demo:利用Sentinel-监测北京奥林匹克森林公园年NDVI变化(附Python版)
开发语言·python·sentinel