我想将MySQL用作作业队列。多台机器将生产和消耗工作。工作需要安排;有些可能每小时运行一些,有些可能每天运行等等。
看起来相当简单:对于每个作业,都有一个“nextFireTime”列,并让工作机器使用nextFireTime搜索作业,将记录的状态更改为“inProcess”,然后在作业时更新nextFireTime结束。
当一个工人无声地死去时,问题就出现了。它将无法更新nextFireTime或将状态设置回“空闲”。
不幸的是,作业可能会长时间运行,因此寻找已经处于过程中的作业的收割者线程不是一种选择。没有超时值可行。
有人能建议一种能够正确处理不可靠的工人机器的设计模式吗?
答案 0 :(得分:4)
也许就像这样
当工作人员提取作业时,可以将其process-id或其他唯一ID添加到作业中的字段
然后在另一个表中,每个工作人员都会不断更新他们活着的值。当更新“我活着”字段时,你会检查所有其他“上一次工人显示生命迹象”。如果一个工人超过限制,找到它正在处理的所有工作并重置它们。
因此换句话说,看门狗是在工作流程而不是工作本身上工作的。
答案 1 :(得分: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这样的东西。如果您能够容忍依赖亚马逊服务,我强烈推荐使用新的亚马逊简单工作流系统(我相信不要求您使用EC2)。
对于您原来的问题:现在我们正在实现一个每节点主管,它可以判断节点的作业是否仍处于活动状态,如果是,则将心跳发送回作业监视器。这很痛苦,但是当您发现并将继续发现时,需要管理很多细节和错误案例。但是,大多数情况下,我必须鼓励您通过了解这个领域并从一开始就正确构建系统来帮助自己。
答案 2 :(得分:1)
一种选择是确保作业是幂等的,并允许多个工作人员启动给定的作业。哪个工人完成工作,或者不止一个工人完成工作并不重要;因为作业的设计方式可以优雅地处理多个完成。也许工人竞赛提供结果,失败者发现保存结果的插槽已经满了,所以他们只是放弃它们。
另一个选择是没有大工作。将长时间运行的作业分解为中间步骤,如果作业花费的时间超过(比如说)1分钟,则将中间结果存储为新作业(以某种方式链接到旧作业),以便新作业可以再次排队再做一分钟的工作。