1

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

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

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

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

编辑

队列通常包含超过 25,000 个项目。

4

4 回答 4

5

也许您可以按队列中的时间加权优先级。这样,任务未完成的时间越长,优先级越高,最终这些任务应该移到列表的顶部。

看起来您已经拥有有关何时记录任务的数据(“created_at”),所以我认为您拥有所需的一切:

SELECT * FROM queue ORDER BY priority*( now() - created_at ) DESC
于 2013-08-15T11:34:21.567 回答
1

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

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

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

处理数据库的系统必须这样做:

every <time interval>:
   X = X + 1

并在插入时设置priority_adjustedpriority负 X。

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

于 2013-08-15T13:50:13.310 回答
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;

应该足够好

于 2013-08-15T11:36:48.047 回答
0

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

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

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

于 2013-08-15T20:37:31.803 回答