如何对繁忙队列进行优先级排序,以便低优先级项目也能得到处理



我们使用mysql表实现了一个基本的作业队列,其中一些项目的优先级低于其他项目。由于队列中不断填充高优先级项目,因此低优先级项目有时永远不会得到处理。

在我们的实现中,我们将项目及其优先级插入到表中,为了从队列中获得下一个项目,我们这样查询表:

SELECT * FROM `queue` ORDER BY `priority` DESC, `created_at` ASC

我们应该如何对队列进行建模,以使优先级较低的项目仍能得到及时处理?

编辑

队列通常包含25000多个项目。

也许您可以根据队列中的时间对优先级进行加权。这样,任务完成的时间越长,优先级就越高,最终这些任务应该会排在列表的首位。

看起来你已经有了关于任务何时被记录的数据("created_at"),所以我认为你已经拥有了所需的一切:

SELECT * FROM queue ORDER BY priority*( now() - created_at ) DESC

实现这一点的经典方法是在挑选一个项目后立即提高队列中每个项目的优先级。这样,较旧的低优先级项目将在某一点上积累足够的优先级,以超过任何新的高优先级项目。

有点像的循环

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;

应该足够好

已经发布了两个答案,一个使用动态计算的时差,另一个涉及整个数据库的更新。第三个不需要这两个选项的选项是在插入新项目时调整优先级值本身。例如,当插入优先级为P的项时,将"priority"列设置为P,并将另一列"priority_adjusted"设置为P-X,其中X是一个每秒钟或每分钟增加一的整数。然后查询

SELECT * FROM `queue` ORDER BY `priority_adjusted` DESC;

按处理顺序返回项,列"priority"包含原始优先级。这应该很快,因为它不需要任何动态计算,也不需要数据库更新。

处理数据库的系统必须执行以下操作:

every <time interval>:
   X = X + 1

并且当插入集合CCD_ 1到CCD_

如果您的优先级值在1..100之间,那么在100个间隔(X增加了100倍)之后,在时间100插入任何项目之前,将处理从时间0开始的所有最低优先级项目。

有时在线程调度中使用的另一种解决方案是在每个优先级中添加一个虚拟项。

在每个优先级级别,项目都是按照到达的顺序进行选择的。当选择当前优先级的虚拟项目时,将触发从较低优先级中选择一个项目,并重新插入队列的后面。

这确保了优先级较低的项目不会被忽略,也不会比优先级较高的项目更快地被拾取。

相关内容

最新更新