简体   繁体   English

如何确保同一工作不会同时运行两次?

[英]How to assure the same job doesn't run twice at the same time?

I have a simple sidekiq job that I've set to run every 5 minutes using clockwork. 我有一个简单的sidekiq工作,我设置使用发条每5分钟运行一次。 What I'm worried about is that, if the job takes longer than 5 minutes, it will run again, which could cause some issues if it's running at the same time as the original job. 我担心的是,如果工作时间超过5分钟,它将再次运行,如果它与原始作业同时运行,可能会导致一些问题。

Is there a way to lock the clockwork so that it only runs if the previous running has completed? 有没有办法锁定发条,以便它只在前一次运行完成后运行?

I've used the Sidekiq Unique Jobs gem to accomplish this. 我使用了Sidekiq Unique Jobs gem来实现这一目标。 It has various strategies for preventing duplicate jobs. 它有各种防止重复工作的策略。

One option is to create a file with the process PID when the job starts, and delete it when the job ends, and abort the job at the beginning if the PID file already exists. 一种选择是在作业启动时创建具有过程PID的文件,并在作业结束时将其删除,如果PID文件已存在则在开始时中止作业。

Although this particular part of my app isn't using sidekiq, the idea is the same. 虽然我的应用程序的这个特定部分没有使用sidekiq,但这个想法是一样的。 Here's how my app does it: https://github.com/WikiEducationFoundation/WikiEduDashboard/blob/master/lib/data_cycle/constant_update.rb 以下是我的应用程序的用法: https//github.com/WikiEducationFoundation/WikiEduDashboard/blob/master/lib/data_cycle/constant_update.rb

Sidekiq allows you to query the queue through the API. Sidekiq允许您通过API查询队列。

You could simply query the sidekiq queue when your task runs. 您可以在任务运行时查询sidekiq队列。 Check to see if the queue and/or job is still there. 检查队列和/或作业是否仍然存在。 If it is, do nothing. 如果是的话,什么都不做。 If it isn't, enqueue the job. 如果不是,请将作业排入队列。

I don't know if your job sits in a separate queue, which would probably be best. 我不知道你的工作是否位于一个单独的队列中,这可能是最好的。 That way you can just view the queue size and if it is 0 then start up another process. 这样您就可以查看队列大小,如果它是0,则启动另一个进程。

Sidekiq API Sidekiq API

Sidekiq Enterprise includes support for unique jobs . Sidekiq Enterprise包括对独特工作的支持。 Unique jobs are defined with an option in the worker class: 使用worker类中的选项定义唯一作业:

# app/workers/my_worker.rb
class MyWorker
  include Sidekiq::Worker
  sidekiq_options unique_for: 10.minutes

  def perform(...)
  end
end

They must be enabled in the Sidekiq initializer as well: 它们必须在Sidekiq初始化器中启用:

# config/initializers/sidekiq.rb
Sidekiq::Enterprise.unique! unless Rails.env.test?

The time window only applies while the job is running, eg, if it is unique for 10 minutes and the job completes in 6 minutes then Sidekiq will immediately allow another job to be enqueued; 时间窗口仅在作业运行时适用,例如,如果它在10分钟内是唯一的,并且作业在6分钟内完成,那么Sidekiq将立即允许其他作业入队; you don't have to wait 4 more minutes for the uniqueness lock to be dropped. 您不必再等待4分钟就可以删除唯一性锁定。

The uniqueness constraint is enforced across all Sidekiq Enterprise nodes. 所有Sidekiq Enterprise节点都实施唯一性约束。

You may need to adjust your retries options because a failed job will continue to hold the lock for as long as it is in a retry state. 您可能需要调整retries选项,因为失败的作业将继续保持锁定,只要它处于重试状态。 (even if it is not actively executing) (即使它没有积极执行)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM