我有ETA任务被发送到Celery的Redis经纪人。它是一个单独的芹菜和redis实例,都在同一台机器上。
问题是,任务多次执行。我看到任务执行了4到11次。
我将可见性超时设置为12小时,因为我的ETA在4-11小时之间(在运行时确定):
BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 12 * 60 * 60}
即便如此,任务仍会多次执行。
最初,有问题的任务不是幂等的,所以我尝试添加数据库检查以使它们具有幂等性。
它看起来像这样:
@app.task
def foo(side_effect_action):
if side_effect_action.executed:
return ALREADY_EXECUTED
else:
do_side_effect()
side_effect_action.executed = True
side_effect_action.save() #hits the db
return JUST_EXECUTED
事实证明芹菜工作者在foo能够调用side_effect_action.save()
之前完成任务并保存状态,因此在所有情况下,当它正在寻找side_effect_action.executed
时,它仍然是假的,因而得到多次执行。
任何想法如何解决这个问题?
答案 0 :(得分:2)
我将芹菜经纪人转到RabbitMQ以避免这个问题。不幸的是,因为我现在在我的webapp中还有一个组件(我还需要redis用于其他东西),但它确实解决了ETA任务错误的多次执行。