我们使用mysql表实现了一个基本的作业队列,其中一些项的优先级低于其余项。由于队列持续填充高优先级项目,因此有时永远不会处理低优先级项目。
在我们的实现中,我们将项目及其优先级插入到表中,并从队列中获取下一个项目,我们查询表格如下:
SELECT * FROM `queue` ORDER BY `priority` DESC, `created_at` ASC
我们应该如何建模队列,以便及时处理较低优先级的项目?
队列通常包含超过25,000个项目。
答案 0 :(得分:5)
也许您可以按队列中的时间加权优先级。这样,优先级会增加任务未完成的时间,最终这些任务应该移到列表的顶部。
看起来你已经有关于记录任务的时间(“created_at”)的数据,所以我认为你有所需的一切:
SELECT * FROM queue ORDER BY priority*( now() - created_at ) DESC
答案 1 :(得分:1)
执行此操作的经典方法是在选择一个项目后立即增加队列中每个项目的优先级。这样,较旧的低优先级项目将在一个点上积累足够的优先级以超越任何新的高优先级项目。
类似于
的循环SELECT * FROM `queue` ORDER BY `priority` DESC, `created_at` ASC LIMIT 1;
-- read selected queue item
DELETE FROM `queue`WHERE <primary key>=<primary key of selected element>;
UPDATE `queue` SET `priority`=`priority`+1;
应该足够好
答案 2 :(得分:1)
已发布两个答案,一个使用动态计算的时差,另一个涉及整个数据库的更新。不需要其中任何一个的第三个选项是在插入新项目时自己调整优先级值。例如,当插入具有优先级P的项目时,将'priority'列设置为P并将另一列'priority_adjusted'设置为P-X,其中X是一个整数,例如每秒或每分钟增加一个。然后查询
SELECT * FROM `queue` ORDER BY `priority_adjusted` DESC;
按处理顺序返回项目,“priority”列包含原始优先级。这应该很快,因为它不需要动态计算任何东西,也不需要数据库更新。
处理数据库的系统必须这样做:
every <time interval>:
X = X + 1
并将priority_adjusted
设置为priority
减去X。
如果您的优先级值介于1..100之间,则在100个间隔(X增加100次)之后,将在时间100之前插入任何项目之前处理时间0的所有最低优先级项目。
答案 3 :(得分:0)
有时在线程调度中使用的替代解决方案是向每个优先级添加虚拟项目。
在每个优先级别,项目按其到达顺序选择。当前优先级的虚拟项目在被选中时将触发从较低优先级中选择项目,并重新插入队列的后面。
这确保较低优先级的项目既不会被忽略也不会比较高优先级的项目更快地被拾取。