在 celerybeat 中一次只运行一个任务

发布于 2024-11-16 14:45:08 字数 183 浏览 3 评论 0 原文

我有一个使用 celerybeat 每分钟执行一次的任务。效果很好。但有时,该任务的运行时间会比一分钟多几秒,因为该任务的两个实例都在运行。这会导致一些竞争条件,使事情变得混乱。

我可以(并且可能应该)修复我的任务以使其正常工作,但我想知道 celery 是否有任何内置方法来确保这一点。我粗略的谷歌搜索和 RTFM 没有得到任何结果。

I have a task which I execute once a minute using celerybeat. It works fine. Sometimes though, the task takes a few seconds more than a minute to run because of which two instances of the task run. This leads to some race conditions that mess things up.

I can (and probably should) fix my task to work properly but I wanted to know if celery has any builtin ways to ensure this. My cursory Google searches and RTFMs yielded no results.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

贪恋 2024-11-23 14:45:08

你可以 添加锁,使用 memcached 或仅使用您的数据库之类的东西。

You could add a lock, using something like memcached or just your db.

兔小萌 2024-11-23 14:45:08

如果您使用 cron 计划或时间间隔来运行定期任务,您仍然会遇到问题。您始终可以使用数据库或缓存甚至文件系统的锁定机制,或者也可以从上一个任务安排下一个任务,这可能不是最好的方法。
这个问题或许可以帮助你:
django celery:如何将任务设置为以编程方式按特定时间间隔运行

If you are using a cron schedule or time interval for run periodic tasks you will still have the problem. You can always use a lock mechanism using a db or cache or even filesystem or also schedule the next task from the previous one, maybe not the best approach.
This question can probably help you:
django celery: how to set task to run at specific interval programmatically

这样的小城市 2024-11-23 14:45:08

您可以尝试向包含您正在运行的函数的对象添加一个类字段,并将该字段用作“其他人是否正在工作”控制

You can try adding a classfield to the object that holds the function that youre making run and use that field as a "some other guy is working or not" control

情泪▽动烟 2024-11-23 14:45:08

锁是配合beat 或cron 的好方法。

但是,请注意,节拍作业在工作器开始时间运行,而不是在节拍运行时运行。

这导致我即使有锁也会出现竞争条件。假设工人下班了,beat 将 10 个工作放入队列中。当 celery 启动 4 个进程时,所有 4 个进程都会获取一个任务,在我的例子中,1 个或 2 个进程会同时获取并设置锁。

解决方案一是使用带锁的 cron,因为 cron 将在那时执行,而不是在工作程序启动时执行。

解决方案二是使用稍微更先进的锁定机制来处理竞争条件。对于 Redis,请查看 setnx 或较新的 redlock
这篇博文非常好,包括一个使用 redis-py 锁定机制的装饰器模式:http://loose-bits.com/2010/10/distributed-task-locking-in-celery.html

The lock is a good way with either beat or a cron.

But, be aware that beat jobs run at worker start time, not at beat run time.

This was causing me to get a race condition even with a lock. Lets say the worker is off and beat throws 10 jobs into the queue. When celery starts up with 4 processes, all 4 of them grab a task and in my case 1 or 2 would get and set the lock at the same time.

Solution one is to use a cron with a lock, as a cron will execute at that time, not at worker start time.

Solution two is to use a slightly more advanced locking mechanism that handles race conditions. For redis look into setnx, or the newer redlock.
This blog post is really good, and includes a decorator pattern that uses redis-py's locking mechanism: http://loose-bits.com/2010/10/distributed-task-locking-in-celery.html.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文