Celery任务Redis存储结果调用get返回None,如何正确获取任务返回数据
问题根因
从你提供的Celery运行日志可以看到:
[2021-12-09 15:08:05,090: INFO/ForkPoolWorker-15] Task get_top_ten_gainers[26ce0da8-662c-4690-b95e-9d1e42e79e34] succeeded in 3.8531467270004214s: None
任务执行成功后返回给Celery的结果本身就是None,并非结果没有存入Redis后端,问题出在任务返回值没有被Celery正常接收。
排查步骤
- 确认任务执行到了return语句:在
return payload前加一行日志logger.info(f"返回payload:{payload}"),检查Worker日志中是否有这行输出,如果没有说明return前的代码出现了隐式中断,如果有则说明返回值被其他逻辑拦截。 - 检查Celery全局配置:确认没有设置
CELERY_IGNORE_RESULT = True,虽然你在任务装饰器中指定了ignore_result=False,部分版本的Celery存在全局配置优先级高于任务级配置的问题。 - 检查任务是否有其他装饰器:如果
get_top_ten_gainers上除了@shared_task还有其他自定义装饰器,要确保装饰器正确透传了原函数的返回值,否则会导致返回值被替换为None。 - 验证结果序列化兼容性:你返回的嵌套列表是标准JSON可序列化结构,可手动测试
json.dumps(payload)是否报错,排除序列化失败导致返回值被清空的可能。
适配你需求的最优方案
你原本的需求是每日执行一次任务缓存查询结果,不需要每次请求都触发任务运行,完全可以跳过Celery Result Backend的逻辑,直接手动操作Redis实现缓存,逻辑更可控,性能也更好:
- 在任务中拿到payload后直接写入Redis固定key,设置24小时过期:
import json import redis redis_client = redis.Redis(host='127.0.0.1', port=6379, db=0) @shared_task(name='get_top_ten_gainers') def get_top_ten_gainers(): # 原有查询逻辑不变,拿到payload后 redis_client.setex("top_ten_gainers", 86400, json.dumps(payload)) return payload
- 用Celery Beat配置每日定时触发该任务,不需要在请求时调用任务。
- Flask端辅助函数直接读取Redis缓存即可:
def _top_ten_gainers(): data = redis_client.get("top_ten_gainers") if not data: # 缓存失效时可选主动触发一次任务兜底 get_top_ten_gainers.delay() return [] total_payload['gainers'] = json.loads(data)
内容的提问来源于stack exchange,提问作者sat1017
相关产品推荐
相关产品推荐

