Ruby中的延迟处理作业:多少不阻塞我的路径

时间:2013-03-18 08:51:18

标签: ruby-on-rails delayed-job resque sidekiq delayed-execution

我有这个项目仍然使用延迟作业作为处理作业队列。我最近发现了一个边缘案例,它让我质疑一些事情:我有这个AR(顺便说一下,我使用MySQL)对象,它在更新时向has_many关联的所有元素发送消息。为了做到这一点,我必须实例化这个关联的所有元素,并在其上调用消息。似乎只是公平地推迟对每一个人的这个消息的召唤。

现在关联已经增长了很多,在边缘情况下,我有40000个属于该关联的对象。因此,由此发送的消息涉及(同步)创建40000个延迟作业作业。由于这些发生在更新后的回调中而不是在提交之后,因此它们(ab)使用相同的连接,而不利用任何上下文切换。简短版本,我在同一个连接上有一个1 Update语句管道和40000个插件。出于这个原因,这个更新在生产中耗费了相当多的时间。

现在,有很多方法可以解决这个问题:将回调更改为提交后,创建1(同步)延迟作业,这将创建40000个作业(我不想在一个中处理40000(AR)对象工作,40000现在明天将是120000,那是记忆 - 世界末日等等......

但我真正考虑的是将延迟处理队列切换为resque或sidekiq。他们使用redis,因此写性能要好得多。他们使用的东西而不是MySQL,这意味着连接不会相互阻塞。我唯一的问题是:40000一次写入redis会花多少钱?并且:这些选项中的任何一个是否首先将作业存储在内存中,而不是阻止对客户端的响应并且迟交将它们存储在redis中?所以,我真正的问题是:在这种边缘情况下,这种拖延会延迟多少?

1 个答案:

答案 0 :(得分:4)

实际上,Redis可以比MySQL更快地处理写入。尝试运行redis-benchmark,您会看到数字为100k +写入/秒。

  

这些选项中的任何一个是否首先将作业存储在内存中,而不是阻止对客户端的响应并且迟交将它们存储在redis中?

不,他们是同步的。

  

我不想在一个作业中处理40000(AR)对象

也许您应该尝试混合方法:每个作业处理N个对象的块。批量写入应该比40k个别写入更快。并且它可以很好地扩展(批量大小将保持不变,无论是40k或400k项目)。