无Worker运行时Redis中Celery任务未堆积的问题排查
使用容器部署Django+Celery架构,生产者容器发送任务,Worker容器处理任务。停止Worker容器后,预期任务会堆积在Redis队列test-dear中,但执行llen test-dear返回0,看不到任务堆积。相关配置如下:
CELERY_DATABASE_NUMBER = 0 CELERY_BROKER_URL = f"redis://{REDIS_HOST}:6379/{CELERY_DATABASE_NUMBER}" CELERY_RESULT_BACKEND = f"redis://{REDIS_HOST}:6379/{CELERY_DATABASE_NUMBER}" CELERY_BROKER_TRANSPORT_OPTIONS = {'global_keyprefix': SHORT_HOSTNAME } # SHORT_HOSTNAME='test-dear' CELERY_TASK_DEFAULT_QUEUE = SHORT_HOSTNAME CELERY_TASK_ACKS_LATE = True
执行任务的步骤:
在生产者容器中进入Django Shell:
python manage.py shell
发送任务:
>>> from cached_dear import tasks >>> t1 = tasks.purge_deleted_masterdata_fast.delay() <AsyncResult: 9c9a564a-d270-444c-bc71-ff710a42049e>
调用t1.get()无返回,Redis中llen test-dear结果为0,与预期不符。
1. Redis键前缀导致队列名称被修改
你配置了CELERY_BROKER_TRANSPORT_OPTIONS = {'global_keyprefix': 'test-dear'},这个参数会给Redis中Celery使用的所有键添加前缀。因此,实际的队列键不是test-dear,而是test-dear:test-dear。
你可以在Redis中执行以下命令查看真实的队列长度:
llen test-dear:test-dear
也可以用keys *查看所有带test-dear前缀的键,确认任务是否存在。
2. 确认Redis数据库是否匹配
你的配置中指定了Redis数据库编号为0,确保你在Redis CLI中连接的是db0(默认即为db0,若有切换需用SELECT 0命令切换),否则查不到对应数据库里的任务。
3. 检查任务是否被自动清理
当没有Worker监听队列时,Celery默认不会丢弃任务,但如果配置了任务过期时间(比如CELERY_TASK_TIME_LIMIT或CELERY_TASK_SOFT_TIME_LIMIT),任务过期后会被自动清理。检查你的配置中是否有相关过期设置,如有需要调整或移除后再测试。
4. 验证任务发送状态
可以在Django Shell中检查任务的具体状态:
>>> from celery.result import AsyncResult >>> res = AsyncResult('9c9a564a-d270-444c-bc71-ff710a42049e') >>> res.state
如果状态是PENDING,说明任务已成功发送到Broker但未被处理;如果是FAILURE,则任务可能在发送过程中出错,需要查看生产者容器的日志排查问题。
内容的提问来源于stack exchange,提问作者Tim Richardson

