我有这个项目,它仍然使用延迟作业作为处理作业队列。我最近发现了一个让我质疑一些事情的边缘案例:我有这个 AR(顺便说一下,我正在使用 MySQL)对象,它在更新时会向 has_many 关联的所有元素发送一条消息。为了做到这一点,我必须实例化这个关联的所有元素,并在它们上调用消息。对他们每个人来说,延迟这个消息的调用似乎只是公平的。
现在该关联已经增长了很多,在极端情况下,我有 40000 个属于该关联的对象。因此,消息发送现在涉及(同步)创建 40000 个延迟作业作业。由于这些发生在更新后回调而不是提交后,因此它们(ab)使用相同的连接,而不是利用任何上下文切换。短版,我在同一连接上有 1 个更新语句和 40000 个插入的管道。出于这个原因,此更新在生产中消耗了相当多的时间。
现在,有很多方法可以解决这个问题:将回调更改为提交后,创建 1 个(同步)延迟作业,这将创建 40000 个作业(我不想在一个作业中处理 40000 个(AR)对象,现在的 40000 明天将是 120000,这就是记忆世界末日),等等……
但我真正考虑的是将我的延迟处理队列切换到 resque 或 sidekiq。他们使用redis,因此写入性能要好得多。他们使用一些东西而不是 MySQL,这意味着连接不会相互阻塞。我唯一的问题是:一次 40000 次写入 redis 会花费我多少钱?并且:这些选项中的任何一个是否首先将作业存储在内存中,而不是阻止对客户端的响应并将它们延迟存储在 redis 中?所以,我真正的问题是:在这种极端情况下,这种延迟会耽误我多少时间?