我的数据库中有 200000 个用户
我需要遍历每条记录来处理一些事情。
所以我有一个 rake 任务来迭代每个用户,主要逻辑将在一个工人中。现在我想获得可以同时运行的工人的限制。如果限制是 50000,那么我可以将我的用户分成 4 个集合,对于每个集合,我将分别调用 Worker。
任务:
namespace :users do
task data: :environment do
confirmed_users = User.where('confirmed_at IS NOT NULL').where('id <= 50000')
confirmed_users.each do |user|
MyWorker.perform_async(user.id)
end#confirmed_users.each do |user|
confirmed_users = User.where('confirmed_at IS NOT NULL').where('id > 50000 and id <= 100000')
confirmed_users.each do |user|
MyWorker.perform_async(user.id)
end#confirmed_users.each do |user|
confirmed_users = User.where('confirmed_at IS NOT NULL').where('id > 100000 and id <= 150000')
confirmed_users.each do |user|
MyWorker.perform_async(user.id)
end#confirmed_users.each do |user|
confirmed_users = User.where('confirmed_at IS NOT NULL').where('id > 200000')
confirmed_users.each do |user|
MyWorker.perform_async(user.id)
end#confirmed_users.each do |user|
end
end
如果我能知道sidekiq的限制,我就可以让用户动态设置。我想知道这是在更短的时间内完成流程的正确方法。或者有什么方法可以在更短的时间内处理我的所有记录?
答案 0 :(得分:1)
Sidekiq 只能同时处理与工作线程/线程一样多的作业。其余的将被放置在队列中,队列实际上是无限的。 20 万个工作没有问题。
您的问题可能来自使用 1 个 sql 查询查询 20 万个作业的速度缓慢,并且在从中创建作业时必须将结果保存在内存中。
使用 find_each
告诉 Rails 批量查找记录并一一产生。
namespace :users do
task data: :environment do
User.where('confirmed_at IS NOT NULL').find_each do |user|
MyWorker.perform_async(user.id)
end
end
end
但是,由于您只需要 id,而不是整个用户对象,我们也可以删除对象启动以加快速度。
User.where('confirmed_at IS NOT NULL').in_batches.each do |batch|
batch.pluck(:id).each do |id|
MyWorker.perform_async(user.id)
end
end
如果这还不够快,还有 Sidekiq::Client.push_bulk
。它只会为每一批次向 redis 发出一个请求。可能需要在此处调整批量大小。
User.where('confirmed_at IS NOT NULL').in_batches.each do |batch|
args = batch.pluck(:id).map { |id| [id] } # args is [[1], [2], [3], etc...]
Sidekiq::Client.push_bulk('class' => MyWorker, 'args' => args)
end