如何安排数十万个任务?

2024-04-27 03:50:57 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

据我所知,我们正在寻找一些东西,以一个固定的时间间隔将任务释放到队列中。(然后工作人员可以从该队列请求任务。)

什么是最大限度地安排重复性任务的最佳方式?在

尽管使用组件(RabbitMQ?)没有问题,但我们主要还是使用Python用其他语言写的。在

更新:现在,我们大约有35万个任务,每半小时运行一次,有些变化。350000个任务*每天48次,即每天执行16800000个任务。在

更新2:没有依赖关系。这些任务不必按顺序执行,也不依赖以前的结果。在


Tags: 机器数据库间隔队列作业方式时间rabbitmq
3条回答

如果您担心写操作,您可以使用一组服务器来分派任务(可能会对服务器进行条带化以均衡负载),并让每个服务器将批量检查点写入数据库(这样,就不会有太多的写入查询)。当然,如果调度服务器死机,您仍然需要写才能恢复。在

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

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

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

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

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

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

当主服务器重新启动时,需要将所有任务id和下次运行时间戳重新加载到内存中,这样可能会对数百万个文件造成痛苦。也许你只需要一个巨大的文件,在文件中给每个task 1K的空间作为属性和下一次运行时间戳,然后使用[task_id]*1K来获得任务属性的正确偏移量。在

如果你愿意使用一个数据库,我相信MySQL可以处理你所描述的任何情况,假设你的主服务器上有4GB+RAM和raid0+1中的几个硬盘驱动器。在

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

相关问题 更多 >