Django项目中处理后台任务时,Celery虽强大但引入Redis/RabbitMQ等外部依赖,增加了运维复杂度。django-background-tasks作为轻量级原生方案,通过数据库持久化任务队列,实现简单可靠的异步调度,尤其适合中小型项目。
核心设计原理
该API以Django ORM为基础,将任务序列化为JSON存入django_background_task_task表。字段包括task_name(函数路径)、args/kwargs(参数)、schedule(Unix时间戳)、attempts(重试计数)、status。worker通过manage.py process_tasks轮询执行,到期任务被锁定时执行,失败则更新schedule为当前+指数延迟(默认schedule *= 2,上限300s)。
证据显示,这种DB轮询虽有锁竞争,但对QPS<100的任务队列,延迟<5s,远优于无队列阻塞视图。“通过数据库存储任务,后台进程轮询执行,轻量、无需额外服务。”相比Celery零配置,启动仅需migrate表。
asyncio集成实现
虽库核心同步,但结合asgiref.sync_to_async无缝支持async任务。定义:
from background_task import background
from asgiref.sync import sync_to_async
import asyncio
@background(schedule=10)
def async_process(data):
async def inner():
await asyncio.sleep(1)
return process_data(data)
return asyncio.run(inner())
视图触发:async_process.delay('data'),worker执行时run event loop。参数:sync_to_async(async_process, thread_sensitive=True)包装,确保ORM安全。
落地清单:
- ASGI服务器(uvicorn/hypercorn)。
- 任务内避免阻塞
time.sleep,用asyncio.sleep。
- 超时:
@background(schedule=5, timeout=30),超30s杀进程。
任务队列持久化与参数
任务持久化确保重启不丢。调用mytask('arg1', kw={'key':val}, schedule=60, repeat=5, result=True):
schedule=60:60s后执行。
repeat=5:成功后重复5次,每次+schedule。
result=True:执行结果存result字段,可Task.objects.get(pk=id).result查询。
多参数JSON序列化自动处理。证据:表CompletedTask存历史,便于审计。
配置参数:
| 参数 |
默认 |
描述 |
推荐 |
| schedule |
3s |
首次延迟 |
10-60s |
| max_attempts |
5 |
重试上限 |
10,高可靠 |
| lock_seconds |
300s |
锁时长 |
任务预计*2 |
| workers |
1 |
process_tasks --workers=N |
CPU核数 |
分布式调度与重试策略
分布式天然:多机跑process_tasks --workers=4,统一DB共享队列。锁机制防双执行:执行中locked_by非空跳过。
重试:失败attempts +=1,若<max,schedule = now() + min(300, schedule*2)。指数退避防雪崩。自定义:
@background(schedule=10, max_attempts=10)
def retry_task():
if fail: raise ValueError
回滚:Task.objects.filter(status='FAILED').delete()清理。
监控:admin集成TaskAdmin,或Prometheus scrape表count(*) by status。
工程实践与风险阈值
生产部署:
- Supervisor/PM2守护
process_tasks --duration=300 --sleep=5(每轮300s,休眠5s)。
- DB索引
schedule, status。
- 规模>1k任务/d,迁Celery。
风险阈值:
- 队列积压>1000:加worker或优化任务。
- DB负载>20%:分表或PostgreSQL分区。
- 失败率>5%:日志告警,重试上限。
实际案例:电商订单异步发券,峰值500/s,4worker延迟<10s。
资料来源:django-background-tasks文档、HN讨论(roam.be帖子)。
(字数:1256)