Ruby 将重试的sidekiq作业放在队列的开头
我有大约100000份工作的sidekiq队列。有些工作失败了,这没关系,因为当sidekiq重试时,它们通常会成功 但是,来自RetrySet的作业被添加到队列的末尾。很长一段时间过去了,直到作业再次被处理Ruby 将重试的sidekiq作业放在队列的开头,ruby,sidekiq,Ruby,Sidekiq,我有大约100000份工作的sidekiq队列。有些工作失败了,这没关系,因为当sidekiq重试时,它们通常会成功 但是,来自RetrySet的作业被添加到队列的末尾。很长一段时间过去了,直到作业再次被处理 如何将重试的作业放在队列的开头,以便优先处理它们?我不认为有什么好的答案,因为如果我记得右侧的KIQ队列使用Redis列表,那么就需要FIFO。重试的作业将在同一队列中排队,因此这意味着它们将始终位于末尾 有一种方法不是很好,也不是我推荐的方法,那就是添加另一个队列,并将作业重试发送到该队
如何将重试的作业放在队列的开头,以便优先处理它们?我不认为有什么好的答案,因为如果我记得右侧的KIQ队列使用Redis列表,那么就需要FIFO。重试的作业将在同一队列中排队,因此这意味着它们将始终位于末尾 有一种方法不是很好,也不是我推荐的方法,那就是添加另一个队列,并将作业重试发送到该队列:
# config/sidekiq.yml
---
:queues:
- default
- my_worker_retries
将工作进程设置为不重试:
class MyWorker
include Sidekiq::Worker
sidekiq_options retry: false
end
确保您的工作人员可预测地引发错误,如下所示:
class MyWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(arg)
raise ArgumentError
end
end
添加一些逻辑来处理该异常,然后通过新创建的队列再次运行此作业:
class MyWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(arg)
begin
raise ArgumentError
rescue ArgumentError => error
MyWorker.set(queue: :my_worker_retries).perform_async(arg)
end
end
end
这意味着任何失败并在my_worker\u retries
队列中排队的作业都可能陷入无限循环——作业失败、获救、排队、再次失败——更糟糕的是,因为您没有使用Sidekiq内置的重试排队机制,没有退避算法来确保重试不会以CPU能够处理的速度启动
整个事情都很脆弱
您可以尝试通过传递一个参数来防止出现这种情况,该参数指示此作业重试了多少次,以便您可以在某个数字后停止:
class MyWorker
include Sidekiq::Worker
sidekiq_options retry: false
MAX_RETRIES = 5
def perform(arg, retries = 0)
raise 'Too many retries' if retries >= MAX_RETRIES
begin
raise ArgumentError
rescue ArgumentError => error
MyWorker.set(queue: :my_worker_retries).perform_async(arg, retries + 1)
end
end
end
您可以将其扩展为拥有自己的退避算法:
MyWorker.set(queue: :my_worker_retries).perform_in((retries + 1).hours, arg, retries + 1)
这些都不理想,但它确实回答了这个问题。我当然希望有比这更好的解决办法
例如,有一些Sidekiq扩展可能会起作用,但我以前从未使用过。我认为您特别要求的东西是不可能的。实际上,如果这些作业具有高优先级,您应该将它们推送到一个单独的队列中。所有作业都具有相同的优先级。只是如果他们失败了并被重试,他们应该优先感谢Anotherm分享你的方法。我宁愿不使用sidekiq重试机制。我害怕讨厌的虫子独自做这件事