如何安排数十万个任务?

时间:2010-03-16 21:28:28

标签: python

我们有成千上万的任务需要以各种任意间隔运行,有些是每小时,有些是每天,等等。这些任务是资源密集型的,需要分布在许多机器上。

现在,任务存储在具有“此时执行”时间戳的数据库中。要查找需要执行的任务,我们在数据库中查询将要执行的作业,然后在任务完成时更新时间戳。当然,这会导致数据库的大量写入负载。

据我所知,我们正在寻找能够以设定的间隔将任务释放到队列中的东西。 (然后工人可以从该队列中请求任务。)

大规模安排重复任务的最佳方法是什么?

虽然我们在很大程度上使用Python,但我们使用其他语言编写的组件(RabbitMQ?)没有问题。

更新:现在我们有大约350,000个任务,每半小时左右运行一次,但有一些变化。 350,000个任务*每天48次,每天执行16,800,000个任务。

更新2:没有依赖项。任务不必按顺序执行,也不依赖于以前的结果。

5 个答案:

答案 0 :(得分:5)

由于不需要ACID,并且您可以使用可能运行两次的任务,我根本不会在数据库中保留时间戳。对于每个任务,创建[timestamp_of_next_run,task_id]列表并使用min-heap存储所有列表。 Python的heapq模块可以为您维护堆。您将能够以最快的时间戳非常有效地弹出任务。当您需要运行任务时,使用其task_id在数据库中查找任务需要执行的操作。任务完成后,更新时间戳并将其放回堆中。 (注意不要更改当前堆中的项目,因为这会破坏堆属性。)

仅使用数据库存储崩溃和重启后仍将关注的信息。如果重启后不需要这些信息,请不要花时间写入磁盘。您仍然需要进行大量的数据库读取操作来加载有关需要运行的任务的信息,但读取要比写入便宜得多。

如果你没有足够的RAM来同时将所有任务存储在内存中,你可以使用混合设置,在那里你可以在接下来的24小时(例如)RAM中保存任务留在数据库中。或者,你可以用C或C ++重写代码,这些内存的内存较少。

答案 1 :(得分:3)

如果您不想要数据库,则可以将下一个运行时间戳和任务ID存储在内存中。您可以将每个任务的属性存储在名为[task_id] .txt的文件中。您需要一个数据结构来存储所有任务,按内存中的时间戳排序,AVL树似乎可以工作,这是一个简单的python:http://bjourne.blogspot.com/2006/11/avl-tree-in-python.html。希望Linux(我假设您运行的是)可以处理目录中的数百万个文件,否则您可能需要在任务ID上进行哈希以获取子文件夹。)

您的主服务器只需要运行一个循环,从AVL树中弹出任务,直到下一个任务的时间戳在将来。然后你可以睡几秒钟然后再开始检查。每当任务运行时,您都会更新任务文件中的下一个运行时间戳并将其重新插入到AVL树中。

当主服务器重新启动时,会有将所有任务id和下一次运行时间戳重新加载回内存的开销,因此数百万个文件可能会很痛苦。也许你只有一个巨大的文件,并为文件中的每个任务提供1K空间的属性和下一个运行时间戳,然后使用[task_id] * 1K来获得任务属性的正确偏移量。

如果您愿意使用数据库,我相信MySQL可以根据您描述的条件处理您丢弃的任何内容,假设您的主服务器上有4GB + RAM和RAID 0 + 1中的多个硬盘驱动器。

最后,如果你真的想变得复杂,Hadoop也可能会工作:http://hadoop.apache.org/

答案 2 :(得分:1)

如果您担心写入,您可以使用一组服务器来分派任务(可以对服务器进行条带化以均衡负载)并让每个服务器向DB写入批量检查点(这样,您就不会有这么多写查询)。当然,如果调度服务器死了,你仍然需要编写才能恢复。

此外,如果时间戳上没有聚集索引,则可以避免在表的末尾有一个热点。

答案 3 :(得分:1)

  

350,000个任务*每天48次   每天执行16,800,000个任务。

要安排作业,您不需要数据库。

数据库适用于更新的内容。此处可见的唯一更新是更改添加,删除或重新安排作业的计划。

Cron使用单个平面文件以完全可扩展的方式完成此任务。

将整个平面文件读入内存,开始生成作业。定期检查fstat以查看文件是否已更改。或者,更好的是,等待HUP信号并使用它重新读取文件。使用kill -HUP通知调度程序重新读取文件。

目前还不清楚你正在更新数据库。

如果数据库用于根据作业完成确定未来的时间表,那么单个数据库就是一个非常好的想法。

如果您正在使用数据库对作业历史进行一些分析,那么您就拥有了一个简单的数据仓库。

  1. 在简单的平面日志文件中记录完成信息(开始时间,结束时间,退出状态,所有内容)。

  2. 处理平面日志文件以创建事实表和维度更新。

  3. 当有人有做分析的冲动时,将平面日志文件的相关部分加载到数据集市中,这样他们就可以进行查询,统计和平均等等。

    不要将每天17,000,000行直接记录到关系数据库中。没有人想要所有这些数据。他们想要摘要:计数和平均值。

答案 4 :(得分:0)

为什么数十万而不是数亿? :恶:

我认为你需要无堆栈python,http://www.stackless.com/。由Christian Tismer的天才创造。

引用

  

Stackless Python是一个增强版   Python编程的版本   语言。它允许程序员   获得基于线程的好处   编程没有性能   和复杂性相关的问题   与传统的线程。该   Stackless增加的 microthreads   Python便宜又轻巧   方便,如果使用的话   适当地,给予以下好处:   改进了计划结构。更多   可读代码。增加程序员   生产率。

用于大型多人游戏。