celery课程

Celery 核心知识点汇总

Celery:Python 分布式任务队列,异步任务、定时任务、任务调度;解耦耗时操作(邮件、推送、数据清洗、爬虫、定时脚本)

一、基础架构(四大组件)

  1. Task(任务) 业务函数,被装饰器 @app.task 标记;支持普通任务、定时任务、任务链。
  2. Worker(工作进程) 消费任务、执行函数;可以单机多进程 / 多协程、多机分布式部署。
  3. Broker(消息中间件,消息代理) 存放待执行任务,Worker 从 Broker 拉取任务。 ✅ 常用:Redis / RabbitMQ
    • RabbitMQ:官方推荐,可靠、支持消息确认、路由;
    • Redis:简单易部署,适合中小型项目;不支持任务可靠投递(断电丢任务风险)
  4. Backend(结果存储,可选) 保存任务返回值、状态;不需要获取结果可关闭。 支持:Redis、MongoDB、Database、RPC

数据流:客户端提交任务 → Broker 排队 → Worker 取任务执行 → 结果存入 Backend

二、基础安装与最小 Demo

1.安装

复制代码
pip install celery
# redis broker额外装redis客户端
pip install redis

2.项目结构 celery_app.py

复制代码
from celery import Celery

# 创建实例
app = Celery(
    "demo",
    broker="redis://127.0.0.1:6379/0",      # broker地址
    backend="redis://127.0.0.1:6379/0"     # 结果后端
)

# 定义任务
@app.task
def add(x, y):
    return x + y

3.启动 worker

复制代码
# 默认前台启动
celery -A celery_app worker --loglevel=info

# Windows注意:celery5.x不再支持默认prefork,使用solo/eventlet(协程)
celery -A celery_app worker -P eventlet --loglevel=info

4.调用任务三种方式

复制代码
from celery_app import add

# 1. 同步调用(直接执行,不进队列)
res = add(2,3)

# 2. 异步调用【核心】发送任务到broker
res = add.delay(2,3)  

# 3. 更灵活:支持队列、路由(指定某个队列)、倒计时
res = add.apply_async(args=(2,3), queue="default", countdown=5)

# 获取任务结果
res.id         # 任务唯一task_id
res.get()      # 阻塞等待结果,可设置超时 res.get(timeout=10)
res.status     # PENDING/STARTED/SUCCESS/FAILURE
res.ready()    # 是否执行完成
res.successful() # 是否成功

三、任务高级特性

1. 任务选项(装饰器参数)

复制代码
@app.task(
    bind=True,               # 开启self参数,可以访问任务实例
    max_retries=3,           # 最大重试次数
    default_retry_delay=10,  # 默认重试间隔s
    ignore_result=True,      # 不保存返回值,关闭backend减轻压力
    time_limit=30,           # 硬超时:超过直接kill进程
    soft_time_limit=25       # 软超时:抛出异常,可捕获处理
)
def demo_task(self):
    try:
        1/0
    except Exception as e:
        # 主动重试
        self.retry(exc=e, countdown=5)

2. 任务编排(组合任务)

复制代码
from celery import group, chain, chord, signature

# signature:任务签名,可预先封装参数
s = add.s(2, 3)
s.delay()

# chain 任务串行:A执行完结果传给B
chain(add.s(1,2) | add.s(10))()

# group 任务并行:同时执行多个任务
group(add.s(1,1), add.s(2,2))().get()

# chord = group + callback:所有并行任务完成后执行回调
chord(group(task1.s(), task2.s()))(callback.s())

3. 任务路由 & 多队列

业务隔离:不同任务投递不同队列,不同 worker 只消费指定队列

复制代码
# 配置路由
app.conf.task_routes = {
    "celery_app.add": {"queue": "math_queue"},
    "celery_app.send_email": {"queue": "email_queue"}
}

# 启动worker只消费指定队列
celery -A celery_app worker -Q math_queue --loglevel=info
celery -A celery_app worker -Q email_queue --loglevel=info

四、定时任务(Celery Beat)

Beat:定时调度器,周期性向 Broker 发送任务;单机运行!多机启动会重复下发任务

方式 1:代码配置定时任务

复制代码
app.conf.timezone = "Asia/Shanghai" # 时区必须配置!否则时间错乱
app.conf.beat_schedule = {
    "every-10s-task": {
        "task": "celery_app.add",
        "schedule": 10.0,     # 间隔秒
        "args": (1,2)  #位置参数
    },
    #每隔10秒运行

    "daily-8-30": {
        "task": "celery_app.add",
        "schedule": crontab(hour=8, minute=30),
        "args": (2, 3),
    },
    # 案例2:每天早上8点30分执行
}

# schedule 也可用crontab
from celery.schedules import crontab
crontab(hour=3, minute=0) # 每日凌晨3点

启动

复制代码
# worker + beat分开启动(推荐生产)
celery -A celery_app worker --loglevel=info
celery -A celery_app beat --loglevel=info

持久化定时任务

默认 beat 定时存在内存,重启丢失;可使用 django-celery-beat 将定时规则存入数据库,动态增删定时任务(Django 项目常用)。

五、Worker 核心启动参数

复制代码
# -A 指定app
# -c 并发进程数(prefork模式)
celery -A app worker -c 4

# 并发池模式
-P prefork   # 默认多进程(Linux推荐)
-P eventlet  # 协程(IO密集任务)
-P solo      # 单进程(Windows调试)

# 后台守护运行(Linux)
celery -A app worker --detach
# 指定队列、名称、日志文件
celery -A app worker -Q queue1 -n worker1@%h --logfile=worker.log

六、重要配置(app.conf)

复制代码
# 任务序列化,Celery 任务要从客户端发到 Broker(Redis/RabbitMQ),**必须把函数参数转换成字符串格式**,这个过程叫**序列化**;
Worker 拿到字符串,再还原成原始数据 → **反序列化**。

app.conf.task_serializer = "json"
app.conf.result_serializer = "json"
app.conf.accept_content = ["json"]

# 任务执行成功后,Backend(Redis)里保存的**返回结果有效期 1 小时**。
超过时间自动删除。
app.conf.result_expires = 3600

# 防止任务无限重试、死循环
app.conf.task_default_retry_delay = 5

# 任务发送后不可修改(预防消息篡改)
app.conf.security_key = "xxx"

# 开启任务确认(RabbitMQ有效)
# Redis broker 原生不支持acks_late可靠消费
app.conf.task_acks_late = True

七、常见状态

  • PENDING:等待执行
  • STARTED:正在执行(默认关闭,需要启用 task_track_started=True
  • SUCCESS:执行成功
  • FAILURE:抛出异常失败
  • RETRY:任务正在重试
  • REVOKED:任务被撤销

撤销任务

复制代码
from celery_app import add
res = add.delay(1,2)
app.control.revoke(res.id, terminate=True) # terminate=True直接kill运行中的worker

八、生产痛点与坑(高频面试)

  1. Redis Broker 消息丢失风险
    • Worker 宕机:正在执行任务丢失;RabbitMQ 支持消息 ACK,Redis 不支持。
    • 解决方案:重要业务改用 RabbitMQ;任务幂等设计。
  2. Beat 多实例重复调度 beat 只能单实例;多服务器部署需要分布式锁(redis 锁保证只启动一个 beat)。
  3. 任务幂等性 网络重试、任务重复下发,业务代码必须支持重复执行不出错。
  4. Worker 卡死、僵尸任务 设置 time_limit 硬超时;IO 密集使用 eventlet 协程池;定期重启 worker。
  5. 结果 Backend 堆积 不用结果就 ignore_result=True;设置 result_expires 自动清理。
  6. Windows 兼容性 celery5 移除 prefork 支持,必须使用 -P solo / eventlet
  7. 不要在任务中操作数据库长连接 worker 进程长期运行,数据库连接超时断开,任务内动态创建连接。

九、Django 集成 Celery 标准结构

复制代码
project/
├── project/
│   ├── __init__.py
│   ├── celery.py   # celery实例
│   ├── settings.py
├── app1/tasks.py   # 业务任务

celery.py

复制代码
import os
from celery import Celery

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
app = Celery("project")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks() # 自动发现各app下tasks.py

__init__.py

复制代码
from .celery import app as celery_app
__all__ = ["celery_app"]

settings.py 中以CELERY_开头配置:

复制代码
CELERY_BROKER_URL = "redis://127.0.0.1:6379/0"
CELERY_RESULT_BACKEND = "redis://127.0.0.1:6379/0"

十、监控

  1. celery flower 可视化监控面板

    pip install flower
    celery -A celery_app flower --port=5555

功能:查看 worker、任务列表、撤销任务、耗时统计。

十一、面试精简提纲

  1. Celery 架构:Broker、Worker、Backend、Task 作用;Redis vs RabbitMQ 区别
  2. 异步任务 delay /apply_async 区别;任务获取结果方式
  3. 任务重试、超时、串行 / 并行任务链
  4. 多队列任务路由场景
  5. Celery Beat 定时任务原理、重复调度问题
  6. 消息丢失、幂等、僵尸任务解决方案
  7. Flower 监控、Django 集成流程

十二、Celery 完整可运行示例(Redis Broker + Backend)

目录结构

复制代码
celery_demo/
├── celery_main.py   # celery入口配置
└── tasks.py         # 所有任务函数

1. 安装依赖

复制代码
pip install celery redis

2. celery_main.py

复制代码
from celery import Celery
from celery.schedules import crontab

# 1. 创建celery实例
app = Celery(
    "celery_demo",
    broker="redis://127.0.0.1:6379/0",
    backend="redis://127.0.0.1:6379/0"
)

# 2. 全局配置
app.conf.update(
    # 序列化配置
    task_serializer="json",
    result_serializer="json",
    accept_content=["json"],

    result_expires=3600,          # 结果1小时过期
    task_default_retry_delay=5,   # 默认重试等待5秒
    task_acks_late=True,          # 延迟确认(仅RabbitMQ有效)
    timezone="Asia/Shanghai",     # 时区,定时任务必备
)

# 3. 任务路由:不同任务分发到不同队列
app.conf.task_routes = {
    "tasks.add": {"queue": "math_queue"},
    "tasks.send_msg": {"queue": "msg_queue"},
}

# 4. 定时任务 Beat 配置
app.conf.beat_schedule = {
    "every-10s-add-task": {
        "task": "tasks.add",
        "schedule": 10.0,
        "args": (10, 20)
    },
    "daily-3-clock": {
        "task": "tasks.send_msg",
        "schedule": crontab(hour=3, minute=0),
        "args": ["凌晨三点定时消息"]
    }
}

==========================
# 自动导入任务1
app = Celery(
    "demo",
    broker="redis://127.0.0.1:6379/0",
    backend="redis://127.0.0.1:6379/0",
    # 关键:include 列表
    include=["tasks", "tasks_msg"] # 自动导入任务
)
# 自动导入任务2
app.autodiscover_tasks(["tasks"])

3. tasks.py(核心任务代码)

复制代码
from celery_main import app

# ======================
# 普通任务:无需重试,不需要self
# ======================
@app.task(ignore_result=True)
def send_msg(content):
    """发送消息,不保存返回结果"""
    print(f"发送消息:{content}")
    return True


# ======================
# 带bind=True、支持重试、超时控制任务
# ======================
@app.task(
    bind=True,
    max_retries=3,
    default_retry_delay=5,
    time_limit=30,      # 硬超时,30s强制杀死进程
    soft_time_limit=25  # 软超时,25s抛出异常
)
def add(self, x, y):
    try:
        print(f"计算 {x} + {y}")
        res = x + y
        return res
    except Exception as e:
        # 手动重试,等待8秒,覆盖全局默认间隔
        self.retry(exc=e, countdown=8)

4. 客户端调用测试 run.py

复制代码
from tasks import add, send_msg
from celery import group, chain, chord

if __name__ == '__main__':
    # 1. 基础异步调用
    res = add.delay(2, 5)
    print("task_id:", res.id)
    # 阻塞获取结果
    print("结果:", res.get(timeout=10))

    # 2. 指定队列调用
    add.apply_async(args=(3, 4), queue="math_queue")

    # 3. chain 串行任务
    # add(1,2)=3 → add(3,10)
    c = chain(add.s(1, 2) | add.s(10))
    print("chain结果:", c().get())

    # 4. group 并行任务
    g = group(add.s(1, 1), add.s(2, 2))
    print("group并行结果列表:", g().get())

    # 5. chord 并行 + 汇总回调
    @app.task
    def sum_callback(num_list):
        return sum(num_list)

    ch = chord(group(add.s(1, 5), add.s(2, 3)))(sum_callback.s())
    print("chord汇总结果:", ch().get())

启动命令(新开多个终端)

终端 1:启动消费 math_queue 的 worker

复制代码
celery -A celery_main worker -Q math_queue -n math_worker@%h --loglevel=info

终端 2:启动消费 msg_queue 的 worker

复制代码
celery -A celery_main worker -Q msg_queue -n msg_worker@%h --loglevel=info

终端 3:启动定时调度 Beat

复制代码
celery -A celery_main beat --loglevel=info

执行测试

复制代码
python run.py
相关推荐
河南凹凸环境艺术设计10 分钟前
性价比高的民宿酒店设计企业
大数据·人工智能·python
wuyk5553 小时前
Python 第三章:列表 List
服务器·开发语言·python
笨鸟先飞,勤能补拙3 小时前
从预测到决策:人工智能与机器学习的系统方法、工程闭环与现实边界
大数据·人工智能·windows·python·机器学习·密码学
MgArcher4 小时前
抖音a_bogus参数逆向实战:JSVMP环境模拟与Hook技术(2025最新)
javascript·爬虫·python
circuitsosk4 小时前
AI输出的“质检员”:构建智能体质量评估、异常检测与人工兜底的三层防线
人工智能·python·microsoft·正则表达式·langchain
要努力点4 小时前
Python入门第六课
开发语言·python
CTA终结者4 小时前
先用小策略练清条件和动作
人工智能·python
Bruce_Liuxiaowei5 小时前
从零到可运行:基于 Vue3 + FastAPI + DeepSeek-V3 的 AI 英语单词学习系统全栈实战
人工智能·python·学习·fastapi·全栈·智能体
ValhallaCoder5 小时前
Leetcode-hot100(2026.08.17)
python·算法·leetcode
W_326005 小时前
Python-OpenCV图像像素与通道:通道拆分合并、深浅拷贝
图像处理·人工智能·python·opencv·机器学习