多个延迟作业进程启动相同的作业

8

我在一个运行多个工作进程的设置中使用Delayed Job。 对于我的问题来说,这并不重要,但是让我们假设我运行了10个工作进程(目前在开发模式下运行)。

我的问题是有时两个不同的工作进程会开始处理相同的作业,调用我的作业对象上的perform方法。

据我所知,Delayed Job使用悲观锁定来防止这种情况发生,但是它似乎有时仍然有足够的时间来窃取作业,以至于第一个工作进程没有时间将其锁定。

我只是想问问是否还有其他人遇到过这个问题,或者是我的设置出了问题。我正在使用Postrgres,并且这种情况在我开发机器和我托管它的Heroku上都会发生。

我将尝试在我的作业内解决它,但是这仍然有点棘手。理想情况下,Delayed Job永远不会处理来自两个进程的相同作业。

谢谢!


我看到了类似的情况。虽然还没有完全追踪清楚,但似乎在检查锁和创建锁之间,多个工作进程正在获取并执行该任务。 - Rob Di Marco
1
我应该说,我发现在初始化程序中设置Delayed::Worker.read_ahead=1似乎可以缓解这个问题。 - Rob Di Marco
遇到了Resque的同样问题,没有找到解决方案。 - Andrey Kryachkov
2
不,我们实际上放弃了并改用了Sidekiq解决方案。我必须说,虽然设置Redis和Sidekiq听起来需要更多的工作,但它非常值得。自从我们改变后,我们的性能大大提高,稳定性也几乎达到了“完美”。自从我们改变后,我们的Sidekiq工作者已经处理了近5000万个作业,没有任何我们没有自己造成的问题。 :) - Kenny Lövrin
@KennyLövrin 真的吗?我正在维护一个严重依赖延迟作业的系统,它非常缓慢和拥挤...而且我们甚至还没有上线!我要去看看这个 Sidekiq 东西。 - abbood
显示剩余3条评论
1个回答

1
我们已经通过12个工作线程使用Delayed Job运行了大约6000万个作业,从未收到此类报告。您的Delayed Job工作程序正在运行什么SQL语句?您是否使用了更改Postgres锁定行为的gem?以下是我使用的DJ SQL语句:
UPDATE "delayed_jobs" SET locked_at = '2014-05-02 21:16:35.419748', locked_by =
'host:whatever.local pid:4729' WHERE id IN (SELECT id FROM "delayed_jobs" 
WHERE ((run_at <= '2014-05-02 21:16:35.415923' 
AND (locked_at IS NULL OR locked_at < '2014-05-02 17:16:35.415947') 
OR locked_by = 'host:whatever.local pid:4729') AND failed_at IS NULL) 
ORDER BY priority ASC, run_at ASC LIMIT 1 FOR UPDATE) RETURNING *

你是否在其他代码中遇到锁定问题?你可以尝试运行两个Rails控制台会话,并执行以下操作:
控制台会话1:
User.find(1).with_lock do sleep(10); puts "worker 1 done" end

控制台会话2:

User.find(1).with_lock do sleep(1); puts "worker 2 done" end

同时启动这两个任务,如果第二个任务在第一个任务结束之前完成,那么你可能会面临比延迟作业更普遍的锁问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接