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