用于大规模任务调度的可扩展作业队列系统

时间:2014-04-01 12:35:52

标签: php queue rabbitmq scalability jobs

情景:

TL; DR - 我需要一个队列系统,用于根据未来的时间戳触发作业,而不是根据插入的顺序触发

我有一个条目的MySQL数据库,它根据时间戳以精确的顺​​序详细说明需要执行的特定事件(主要包括一系列算术计算和数据库插入/更新)。插入条目的时间和“执行”事件的时间没有相关性,并且由外部因素决定。该表还包含第二列毫秒数,可提高计时精度。

此表是作业“队列”的一部分,该队列将包含设置为在将来几秒到几天之间的任何位置执行的条目,并且每秒可能最多添加数千个条目。需要不断地解析队列(每秒?) - 可能通过选择在此秒期间已过期并按毫秒排序的所有时间戳,然后执行条目详细说明的每个事件。

问题

目前,后端完全用PHP编写,带有MySQL的apache服务器(即标准LAMP架构)。现在,我能想到实现我已经指定的唯一方法是编写一个自定义PHP作业队列脚本,它将执行解析和执行,每秒使用this method循环。我不知道哪个其他作业系统可以根据指定的时间戳/毫秒而不是输入时间来排队作业。

然而,即使在纸上,这种方法听起来也是不可行的 - 我必须每秒执行一次巨大的MySQL查询并为检索到的每一行执行某种功能,并且它可能会在执行时间的一秒钟内运行开始引入解析时间延迟并弄乱循环脚本。

我当然正在尝试创建一个可扩展的解决方案,如果系统有大量流量,这个解决方案会失败,因为随着条目数量的增加,它将继续落后。

问题

我更倾向于坚持使用标准的LAMP架构,但是有没有其他技术可以很好地集成到堆栈中,以便更好地处理我在这里尝试做的事情?

是否还有另一种方法可以在指定的未来日期准确触发事件,而不会对常量队列检查进行麻烦的调整?

如果以上两个选项都不合适,是否有更好的方法在后台循环PHP脚本?在最糟糕的情况下,我可以接受较长的执行时间,并在多个“工人”之间分配任务。

更新

RabbitMQ是一个很好的建议,但不幸的是,它不会在“任期到期”后立即执行任务 - 它必须首先通过队列并等待前面尚未到期的任何任务。到期时间在几秒到几天之间有很大的范围,并且每次添加新事件时都需要以某种方式对队列进行排序,因此到期时间总是在队列中按顺序排列。就我在RabbitMQ中所知,这是不可能的,并且听起来效率也不高。是否有替代方案或程序化修复方法?

1 个答案:

答案 0 :(得分:0)

有时,将方形钉固定在圆孔中需要花费太多精力。使用MySQL创建队列可能很有效,但扩展起来要复杂得多。我建议这可能是RabbitMQ的机会。

基本上,您可以设置一个可以将事件放入的消息队列。然后,您将拥有一个“扇出”架构,您的工作人员可以处理每个队列。每个工作人员都会监听队列并检查是否需要处理特定事件。我想,Rabbit中提供的"Work Queues""Routing"技术的组合将以可扩展且可靠的方式实现您的目标。

我想要一个像这样的系统:

  1. 产生工作人员以侦听队列,使用路由键来删除他们获得的消息数量
  2. 每个工作人员检查消息以查看他们现在是否要执行
  3. 如果要执行该消息,则执行该消息并确认 - 否则,重新分派该消息以供将来处理。有一些simple techniques可用于此。
  4. 随着您需要更多比例,您可以添加更多工作人员。 RabbitMQ非常强大,并且当您最终限制队列服务器时也很容易集群。还有其他基于云的排队系统,例如Iron.IOStormMQ