我正在寻找推荐的解决方案来解决celerybeat是芹菜/ rabbitmq部署的单点故障。到目前为止,我没有找到任何有意义的东西,通过网络搜索。
在我的情况下,每天定时调度员开始一系列可能运行半天或更长时间的工作。由于只能有一个celerybeat实例,如果它发生了某些事情或它正在运行的服务器,将无法运行关键作业。
我希望已经有一个可行的解决方案,因为我不能成为唯一需要可靠(集群或类似)调度程序的人。如果我不需要,我不想诉诸某种数据库支持的调度程序。
答案 0 :(得分:5)
芹菜github回购中存在一个未解决的问题。不知道他们是否正在研究它。
作为一种解决方法,您可以为任务添加锁,以便一次只运行一个特定PeriodicTask实例。
类似的东西:
if not cache.add('My-unique-lock-name', True, timeout=lock_timeout):
return
确定锁定超时是非常棘手的。如果不同的celerybeats尝试在不同的时间运行它们,我们将使用0.9 *任务run_every秒。 0.9只是留下一些余量(例如,当芹菜稍微落后于计划一次,那么它按计划进行会导致锁定仍然有效)。
然后你可以在所有机器上使用celerybeat实例。每个任务都将排队等待每个celerybeat实例,但只有一个任务将完成运行。
任务仍然会以这种方式尊重run_every - 最糟糕的情况:任务将以0.9 * run_every速度运行。
这种情况的一个问题是:如果任务已排队但未在预定时间处理(例如因为队列处理器不可用) - 则可能会在错误的时间进行锁定,从而导致可能的下一个任务无法运行。要解决这个问题,你需要某种检测机制来确定任务是否或多或少。
但是,在生产中使用时,这应该不是常见的情况。
另一种解决方案是将celerybeat Scheduler子类化并覆盖其tick方法。然后为每个刻度添加锁定,然后再处理任务。这可以确保只有具有相同周期性任务的celerybeats不会多次排队相同的任务。每个蜱只有一个celerybeat(一个赢得比赛条件的人)将排队任务。在一个celerybeat下降,下一个滴答,另一个将赢得比赛。
这当然可以与第一种解决方案结合使用。
当然,为了工作,需要为所有服务器复制和/或共享缓存后端。
这是一个老问题,但我希望它可以帮助任何人。