我正在使用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
很可能你的父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进程在处理长时间运行的父进程时会死掉。