我在rails应用程序中要执行以下任务:
由于我想在后台作业中实现这一点,因此我使用了一个处理队列的resque worker。
对于第一份工作,我创建了一个这样的队列
执行任务的@queue = :download_video
,在任务结束时,我将通过调用Resque.enqueue(ConvertVideo, name, itemId)
继续执行下一个任务。通过这种方式,我创建了一个队列链,这些队列在一个任务完成时排队。
这是非常错误的,因为如果第一个作业开始将其他作业(一个来自另一个作业)排队,那么在第一个排队作业列表完成之前,所有作业都会被1个作业者阻止。
如何优化?我试图通过这种排队工作的方式增加更多工人,但结果是错误的,不可预测的。
另一个方面是每个作业都在数据库中保存状态,我需要按正确的顺序处理作业。
每个工人是否应该从上面做一份工作并且至少有4名工人?如果我把这个数量加倍到8个工人,这会有所改善吗?
答案 0 :(得分:0)
您是否考虑过使用sidekiq?
如Sidekiq文件所述:
resque使用redis进行存储并在单线程进程中处理消息。与delayed_job相比,redis要求使设置更加困难,但redis作为队列比SQL数据库好得多。单线程意味着并行处理20个作业需要20个进程,这可能需要大量内存。
sidekiq使用redis进行存储并在多线程进程中处理作业。设置resque同样容易,但在原始处理速度方面更高效。您的工作人员代码确实需要是线程安全的。
所以你应该有两种工作:下载视频和转换视频,任何下载视频作业应该并行完成(如果你愿意,你可以限制)然后每个存储在一个队列中(“中间队列” “)在被多个转换作业并行转换之前。
我希望有所帮助,这个链接很好地解释了Sidekiq的最佳实践:https://github.com/mperham/sidekiq/wiki/Best-Practices
答案 1 :(得分:0)
正如@Ghislaindj所说,Sidekiq可能是另一种选择 - 主要是因为它提供了控制执行顺序的插件。
请参阅此列表:
https://github.com/mperham/sidekiq/wiki/Related-Projects#execution-ordering
但是,是的,您应该使用不同的队列和更多特定于队列的工作者。因此,您有一组工作人员都在:download_video
队列上工作,然后是其他工作人员连接到:convert_video
队列等。
如果您想继续使用Resque,则另一种方法是使用延迟执行,因此当您将后续作业排入队列时,请指定延迟参数。
Resque.enqueue_in(10.seconds, ConvertVideo, name, itemId)
在Resque中使用延迟执行的缺点是它需要resque-scheduler
包,所以你引入了一个新的依赖:
https://github.com/resque/resque-scheduler
为了比较,Sidekiq推迟了本地可用的执行。
答案 2 :(得分:0)
您是否考虑将所有四项任务合并为一项?在这种情况下,您可以拥有任意数量的工人,一个人可以完成这项工作。它将非常可预测,你甚至可以知道完成任务需要多少时间。当其中一个子任务比其他子任务花费更长时间并且它在队列中堆积时,你也没有问题。