2

我想使用 MySQL 作为作业队列。多台机器将生产和消耗工作。需要安排工作;有些可能每小时运行,有些每天运行,等等。

看起来相当简单:对于每个作业,都有一个“nextFireTime”列,让工作机器使用 nextFireTime 搜索作业,将记录的状态更改为“inProcess”,然后在作业结束时更新 nextFireTime。

当一个工人默默地死去时,问题就出现了。它将无法更新 nextFireTime 或将状态设置回“空闲”。

不幸的是,作业可能会长时间运行,因此无法选择寻找已在进程中时间过长的作业的 reaper 线程。没有超时值可以工作。

任何人都可以建议一种可以正确处理不可靠工作机器的设计模式吗?

4

3 回答 3

4

使用 MySQL 作为作业队列通常会以痛苦告终,因为它非常不适合 RDBMS 的通常目标。用户“toong”已经链接到https://www.engineyard.com/blog/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you,它有一个很多有趣的事情要说。不可靠的工人只是并发症之一。

有很多很多用于处理作业分配的系统,它们的主要特点是其排队和调度功能的复杂性。在简单的 FIFO 端是 Resque、Celery、Beanstalkd 和 Gearman;在复杂的一端是 GridEngine、Torque/Maui 和 PBS Pro。如果您可以容忍对 Amazon 服务的依赖,我强烈推荐新的 Amazon Simple Workflow 系统(我相信它不需要您在 EC2 中)。

对于您最初的问题:现在我们正在实施一个每个节点的监督者,它可以判断节点的作业是否仍然处于活动状态,如果是,则将心跳发送回作业监视器。这很痛苦,但是当您正在发现并将继续发现时,有很多细节和错误案例需要管理。不过,大多数情况下,我必须鼓励您通过了解这个领域并从一开始就正确构建系统来帮自己一个忙。

于 2012-03-24T05:24:05.837 回答
4

也许像这样

当工作人员获取作业时,它可以将其进程 ID 或另一个唯一 ID 添加到作业中的字段

然后在另一个表中,每个工人不断更新他们还活着的值。更新“我还活着”字段时,您会检查所有其他“最后一次工人显示出生命迹象”。如果一名工作人员超过限制,请找到它正在处理的所有工作并重置它们。

所以换句话说,看门狗在工作进程而不是工作本身上工作。

于 2011-08-11T18:12:00.453 回答
1

一种选择是确保工作是幂等的,并允许多个工人开始一项给定的工作。哪个工人完成工作,或者是否有多个工人完成工作都没有关系;因为作业的设计方式可以优雅地处理多个完成。也许工人竞相提供结果,而失败者发现保存结果的位置已经满了,所以他们就放弃了。

另一种选择是没有大工作。将长时间运行的作业分解为中间步骤,如果作业花费的时间超过(例如)1 分钟,将中间结果存储为新作业(以某种方式与旧作业的链接),以便新作业可以再次排队再做一分钟的工作。

于 2011-08-11T18:16:19.697 回答