在 celerybeat 中一次只运行一个任务
我有一个使用 celerybeat 每分钟执行一次的任务。效果很好。但有时,该任务的运行时间会比一分钟多几秒,因为该任务的两个实例都在运行。这会导致一些竞争条件,使事情变得混乱。
我可以(并且可能应该)修复我的任务以使其正常工作,但我想知道 celery 是否有任何内置方法来确保这一点。我粗略的谷歌搜索和 RTFM 没有得到任何结果。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你可以 添加锁,使用 memcached 或仅使用您的数据库之类的东西。
You could add a lock, using something like memcached or just your db.
如果您使用 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
您可以尝试向包含您正在运行的函数的对象添加一个类字段,并将该字段用作“其他人是否正在工作”控制
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
锁是配合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.