分布式Celery调度器

13 投票
3 回答
7222 浏览
提问于 2025-04-16 23:17

我在找一个可以在Python中使用的分布式定时任务框架,发现了Celery。不过,文档里说“你必须确保同一时间只有一个调度器在运行,否则会出现重复的任务。”Celery使用的是celery.beat.PersistentScheduler,它会把调度信息存储在本地文件里。

所以,我想问一下,有没有其他的实现方式,可以把调度信息放到集群里,并协调任务执行,确保每个任务只运行一次?我的目标是能够在集群中的所有主机上运行相同的celerybeat调度。

谢谢!

3 个回答

0

我们之前也遇到过同样的问题,三个服务器上都在运行Celerybeat。不过我们的解决办法是只在一台服务器上运行Celerybeat,这样就不会出现重复的任务。你可能会问,为什么要在多台服务器上运行Celerybeat呢?

如果你担心Celery会出现故障,可以写一个脚本来监控Celerybeat进程是否还在运行。

$ ps aux | grep celerybeat

这个脚本可以告诉你Celerybeat进程是否在运行。然后再写一个脚本,如果发现进程停止了,就给系统管理员发邮件。这里有一个示例设置,我们只在一台服务器上运行Celerybeat。

0

我觉得大家可能对celerybeat的功能有些误解。celerybeat并不是用来处理定时任务的,它只是负责发布这些任务。它会把定时任务放到一个队列里,然后由celeryd的工作进程去处理。如果你只运行一个celerybeat进程,但有多个celeryd进程在工作,那么这些任务的执行就会在这些进程之间分配。

15

总结一下: 不,Celerybeat 不适合你的情况。你只能运行一个 celerybeat 进程,否则你的任务会被重复执行。

我知道这个问题很老了。我想简单总结一下,因为我在2018年也遇到过同样的问题。

背景介绍:我们在 Kubernetes 集群中运行 Django 应用(使用 Celery)。这个集群(EC2 实例)和 Pods(类似容器)是自动扩展的:简单来说,我不知道应用有多少个实例在运行。

你需要确保只运行一个 celerybeat 进程,否则你的任务会重复执行。 [1] 在 Celery 的代码库中曾有一个功能请求: [2]

要求用户确保在他们的集群中只有一个 celerybeat 实例,这会带来很大的实现负担(要么造成单点故障,要么鼓励用户自己实现分布式互斥锁)。

celerybeat 应该提供一种机制来防止意外的并发执行,或者文档中应该建议一种最佳实践的方法。

经过一段时间,这个功能请求被 Celery 的作者拒绝了,理由是缺乏资源。 [3] 我强烈建议你阅读 GitHub 上的整个讨论。那里的用户推荐了以下项目/解决方案:

我没有尝试上面提到的任何方案(我不想在我的应用中增加新的依赖,也不喜欢锁定任务,因为你需要处理故障转移等问题)。

最后我选择在 Kubernetes 中使用 CronJob(https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/)。

[1] celerybeat - 多个实例与监控

[2] https://github.com/celery/celery/issues/251

[3] https://github.com/celery/celery/issues/251#issuecomment-228214951

撰写回答