代码之家  ›  专栏  ›  技术社区  ›  Parand

类cron循环任务调度程序设计

  •  8
  • Parand  · 技术社区  · 14 年前

    假设您要计划定期任务,例如:

    • 每周三上午10点发送电子邮件
    • 在每月的第一天创建摘要

    你想为一个网络应用中的合理数量的用户做这件事——也就是说,10万个用户每个用户都可以决定他们想要什么时间安排。

    你要确保计划的项目运行,即使它们最初被错过了-例如,由于某种原因,电子邮件没有在星期三上午10点发送,它应该在下一个检查间隔发送,比如星期三上午11点。

    你会怎么设计?

    如果您使用cron每隔x分钟触发一次调度应用程序,那么实现决定在每个时间点运行什么的部分的一个好方法是什么?

    我看到的类似cron的实现将当前时间与所有指定项的触发时间进行比较,但我也希望处理错过的项。

    我觉得有一个比我正在做的更聪明的设计,所以请启发我。

    3 回复  |  直到 14 年前
        1
  •  6
  •   Will Hartung    14 年前

    基本上有两种设计。

    定期运行并将当前时间与调度规范进行比较(例如,“现在运行吗?”),并执行那些符合条件的。

    另一种技术采用当前的调度规范,并在下一次触发该项时找到它。然后,它将当前时间与“下一次”小于“当前时间”的所有项目进行比较,并触发这些项目。然后,当一个项目完成后,它会重新安排为新的“下一次”。

    第一种技术不能处理“丢失的”项目,第二种技术只能处理那些先前计划的项目。

    具体来说,考虑到你有一个每小时运行一次的时间表,在一个小时的顶部。

    比如说,下午1点,2点,3点,4点。

    下午1:30,运行任务关闭,不执行任何进程。直到下午3:20才重新开始。

    使用第一种技术,调度程序将触发1pm任务,但不会触发2pm和3pm任务,因为这些时间过去时它没有运行。下一个要运行的作业是下午4点的作业,是的,下午4点。

    使用第二种技术,调度程序将启动1pm任务,并在2pm调度下一个任务。由于系统关闭,下午2点的任务没有运行,下午3点的任务也没有运行。但是,当系统在3:20重新启动时,它发现它“错过”了下午2点的任务,并在3:20启动了它,然后又将其安排在下午4点。

    每种技巧都有它的起伏。用第一种方法,你会错过工作。使用第二种技术,你仍然可以错过工作,但它可以“赶上”(某一点),但它也可能“在错误的时间”运行一个工作(可能出于某种原因,它应该在最高峰时间运行)。

    第二种技术的一个好处是,如果在执行作业结束时重新计划,就不必担心级联作业问题。

    想想你有一份每分钟都在运行的工作。用第一种方法,工作每分钟都会被解雇。但是,通常情况下,如果作业在几分钟内没有完成,那么您可能有两个作业正在运行(一个在进程后期,另一个在启动)。如果作业设计为不同时运行一次以上,则这可能是一个问题。而且这种情况会恶化(如果真的有问题,10分钟后,你就有10份工作,所有的工作都在互相竞争)。

    使用第二种技术,如果您在作业结束时调度,那么如果一个作业刚好运行超过一分钟,那么您将“跳过”一分钟并启动下一分钟,而不是在其上运行。所以,你可以把每分钟的作业安排在下午1:01、1:03、1:05等等。

    根据你的工作设计,这两者中的任何一个都可以是“好”或“坏”。这里没有正确的答案。

    最后,与实现第二种技术相比,实现第一种技术确实是非常微不足道的。与派生cron字符串下一个有效时间相比,确定cron字符串是否匹配给定时间的代码很简单。我知道,我有几百行代码可以证明这一点。它不漂亮。

        2
  •  4
  •   Community    7 年前

    如果你想跳过设计,开始使用,看看芹菜。 http://celeryproject.org/ . 调度程序称为celerybeat。

    编辑: 也相关: How to send 100,000 emails weekly?

        3
  •  2
  •   Community    7 年前

    使用支持的Java进程 Quartz scheduler 可能是一个潜在的解决方案。我相信石英应该能很好地达到这个水平。请参阅相关的SO问题: "How to scale the Quartz Scheduler"

    如果您仔细查看Quartz文档,我想您会发现,您对触发和错过执行的担忧得到了清晰的处理,并提供了一些合适的策略供您选择。在可伸缩性方面,我相信您可以将作业存储在JDBC后备存储中。

    出其不意,因为发问者是专门寻找一个设计讨论… 如果在以“针对python的任务调度程序”的形式提出问题之前对初始stackoverflow搜索进行了框架化,则会出现以下情况: "An enterprise scheduler for python..." . 我强烈建议寻找一个现有的实现,而不是尝试NIH开发类似的东西,尽管在另一个答案中有关于如何做到这一点的大量观察。考虑到您所陈述的可伸缩性目标,您将完成一项相当具有挑战性的任务,并且应该消除 全部的 其他选择之前,从零开始的道路上的一个主题,如这一个严重发展。考虑的一个可能途径是适应受人尊敬的 Quartz 通过Jython,并确定您的用例是否可以在该上下文中处理,而最小化到Java世界中(可能不是您的第一选择)。