在我的情况下,每天定时安排一次可以运行半天或更长时间的工作.由于只能有一个Celerybeat实例,如果发生了某些事情或运行的服务器,则不会运行关键作业.
我希望已经有了一个可行的解决方案,因为我不能成为唯一需要可靠(集群等)调度程序的人.我不想诉诸某种数据库支持的调度程序,如果我不必.
作为解决方法,您可以为任务添加一个锁,以便一次只运行一个特定PeriodicTask的实例.
就像是:
if not cache.add('My-unique-lock-name',True,timeout=lock_timeout): return
想出锁定超时是很好的,棘手的.如果不同的celerybeats尝试在不同的时间运行,我们正在使用0.9 *任务run_every秒.
0.9只是为了留下一些余地(例如,当芹菜有一点落后于时间表,那么它是按计划,将导致锁仍然是活动的).
那么您可以在所有机器上使用celerybeat实例.每个任务将排队等待每个芹菜节实例,但只有一个任务将完成运行.
任务仍然会以这种方式尊重run_every – 最坏的情况:任务将以0.9 * run_every速度运行.
这种情况的一个问题是:如果任务排队但未在预定的时间进行处理(例如因为队列处理器不可用) – 那么锁定可能会被置于错误的时间,从而导致下一个任务不能运行.要解决这个问题,您将需要某种检测机制,无论任务是或多或少的准时.
然而,在生产中使用这不应该是常见的情况.
另一个解决方案是将Celerybeat Scheduler子类化并覆盖其tick方法.然后对于每个刻度在处理任务之前添加一个锁.这样可以确保只有具有相同周期性任务的celerybeats不会多次排列相同的任务.每个蜱虫只有一个芹菜(一个赢得比赛条件)将排队任务.在一个芹菜中,下一个选择,另一个将赢得比赛.
这当然可以与第一个解决方案结合使用.
当然这个工作缓存后端需要复制和/或共享所有的服务器.
这是一个老问题,但我希望它能帮助任何人.