意外的sidekiq作业得到执行

时间:2019-04-18 22:17:27

标签: ruby-on-rails sidekiq

我正在使用sidekiq cron来运行一些作业。我有一个仅运行一次的父级工作,并且该父级工作启动了700万个子级工作。但是,在我的sidekiq仪表板中,它说有4200万个工作被排队。我检查了那些排队的工作,它们是我的孩子工作。我试图弄清楚为什么排队了比预期多的工作。我在sidekiq中检查了日志,我注意到的一件事是,“ Cron Jobs-添加名称为new_topic_post_job的作业”在日志中显示了很多次。 new_topic_post是schedule.yml中父作业的名称。以下几行也出现了很多次

2019-04-18T17:01:22.558Z 12605 TID-osb3infd0 WARN: Processing recovered job from queue queue:low (queue:low_i-03933b94d1503fec0.nodemodo.com_4): "{\"retry\":false,\"queue\":\"low\",\"backtrace\":true,\"class\":\"WeeklyNewTopicPostCron\",\"args\":[],\"jid\":\"f37382211fcbd4b335ce6c85\",\"created_at\":1555606809.2025042,\"locale\":\"en\",\"enqueued_at\":1555606809.202564}"
2019-04-18T17:01:22.559Z 12605 TID-osb2wh8to WeeklyNewTopicPostCron JID-f37382211fcbd4b335ce6c85 INFO: start

WeeklyNewTopicPostCron是父作业类的名称。想知道这是否意味着我的父级工作可以运行多次而不是仅运行1次?如果是这样,原因是什么?我很确定cron作业的时间是正确的,我将其设置为“ 0 17 * * 4”,这意味着它每周仅运行一次。另外,我将父项工作的重试设置为false,子项工作的重试设置为3。因此,即使所有儿童工作都失败了,我们仍然应该只有2100万个工作。以下是我在schedule.yml中的cron作业设置

new_topic_post_job:
  cron: "0 17 * * 4"
  class: "WeeklyNewTopicPostCron"
  queue: low

这是WeeklyNewTopicPostCron:

class WeeklyNewTopicPostCron
  include Sidekiq::Worker

  sidekiq_options queue: :low, retry: false, backtrace: true

  def perform
    processed_user_ids = Set.new
    TopicFollower.select("id, user_id").find_in_batches(batch_size: 1000000) do |topic_followers|
      new_user_ids = []
      topic_followers.map(&:user_id).each { |user_id| new_user_ids << user_id if processed_user_ids.add?(user_id) }
      batch_size = 1000
      offset = 0
      loop do
        batched_user_ids_for_redis = new_user_ids[offset, batch_size]
        Sidekiq::Client.push_bulk('class' => NewTopicPostSender, 
                                  'args' => batched_user_ids_for_redis.map { |user_id| [user_id, 7] }) if batched_user_ids_for_redis.present?
        break if batched_user_ids_for_redis.size < batch_size
        offset += batch_size
      end
    end
  end
end

1 个答案:

答案 0 :(得分:1)

您的父sidekiq作业很可能导致sidekiq进程崩溃,然后导致工作线程重新启动。在重新启动时,sidekiq可能会尝试恢复中断的作业并再次开始处理(从头开始)。一些细节在这里: https://github.com/mperham/sidekiq/wiki/Reliability#recovering-jobs

这可能在父作业最终完成之前发生了多次,因此创建了大量子作业。您可以通过在运行此作业时检查sidekiq进程的进程ID来轻松地验证这一点,一段时间后它很可能会不断更改:

ps aux | grep sidekiq

在内存使用率过高的情况下,可能有一些monit配置来重新启动sidekiq。或者可能是此查询导致进程崩溃:

TopicFollower.select("id, user_id").find_in_batches(batch_size: 1000000)

尝试减少batch_size。 100万感觉太高了。但我最大的猜测是,sidekiq进程在处理长时间运行的父进程时会死掉。