2010-07-12 133 views
3

我正在使用Python GAE SDK。Google App Engine:如何使用任务队列进行此处理?

我有一些处理需要在的6000多个实例上完成。在单个请求中执行速度太慢,所以我正在使用任务队列。如果我只让一个任务处理一个实体,那么它只需要几秒钟。

documentation表示只能在“批次”中添加100个任务。 (这是什么意思?在一个请求中?在一个任务中?)

所以,假设“批处理”的意思是“请求”,我试图找出最好的方法是创建一个任务数据存储中的每个实体。你怎么看?

如果我可以假设MyKind的顺序永远不会改变,那么会更容易。 (处理永远不会改变MyKind实例 - 它只会创建其他类型的新实例。)我可以完成一大堆任务,给每个任务启动一个偏移量,间隔小于100。然后,每个任务都可以创建执行实际处理的单个任务。

但是如果有太多的实体,原始请求无法添加所有必要的调度任务会怎么样?这让我觉得我需要一个递归解决方案 - 每个任务都会查看它给出的范围。如果在该范围内仅存在一个元素,则对其进行处理。否则,它会将范围细分为后续任务。

如果我不能指望使用偏移和限制来识别实体(因为它们的顺序不能保证是恒定的),也许我可以使用它们的键?但随后我可能会发送1000个左右的密钥,这似乎很笨重。

我在这里走正确的道路,还是应该考虑另一种设计?

+0

我面临同样的问题。看看我想要做什么http://stackoverflow.com/questions/3211916/how-fast-google-app-engine-is 看到我的第二个答案。如果你找到任何解决方案,请告诉我。 – Manjoor 2010-07-13 13:54:38

回答

9

当您运行代码taskqueue.add(url='/worker', params={'cursor': cursor})时,您正排队执行任务;使用您提供的参数调度带外执行请求。您可以在一次操作中安排多达100个。

虽然我不认为你想。任务链将使这个简单了很多:

你工作者的任务将做这样的事情:

  • 运行查询来处理获取一些记录。如果在任务参数中提供了游标,请使用它。将查询限制为10条记录,或者您认为可以在30秒内完成的任何内容。

  • 处理您的10条

  • 如果您的查询返回的10条记录,排队另一个任务,并从您的查询传递更新的光标,它可以拿起你离开的地方。

  • 如果您的记录少于10条,则表示完成。万岁!发一封电子邮件或其他东西并退出。

有了这条路线,您只需启动第一个任务,剩下的就自己添加了。

请注意,如果某个任务失败,则App Engine将重试该任务直至成功为止,因此您不必担心数据存储区打嗝导致一个任务超时并断开连锁。

编辑:

上述步骤不保证实体将只处理一次。任务通常只应运行一次,但Google建议您为幂等性设计。如果它是一个主要关注点,这里的处理的一种方式:

  • 放在每个实体的状态标志进行处理,或创建一个互补的实体持有的标志。它应该有类似于待处理,处理和处理的状态。

  • 当您获取要处理的新实体时,事务锁定并递增处理标志。只有在实体处于待处理状态时才运行该实体。处理完成后,再次增加标志。

请注意,在开始之前将处理标志添加到每个实体并不是必须的。您的“挂起”状态可能意味着该财产或相应的实体尚不存在。

+0

好吧,如果我这样做,我可以确定所有记录都会被处理一次,而不是更多? – 2010-07-12 05:21:09

+0

编辑为考虑重复处理。 – 2010-07-12 12:58:07

0

也取决于你的设计,你可以做我做的,这是所有需要处理的记录的编号。我处理了大约3500件物品,每件需要3秒左右的时间来处理。为了避免重叠,超时并考虑到未来的扩展,我的第一个任务从数据库中获取所有这类独特项目的列表。然后它将其分成500个每个项目标识符的列表,循环直到它占据我数据库中的所有唯一项目,并将每个500个标识符块发布到第二层处理程序任务。每个第二处理程序任务(当前是七个或八个不同的任务)都有一个唯一的500个项目列表,每个处理程序任务添加500个任务,每个唯一标识符一个。

因为它都是通过循环和基于我的数据库中唯一项目的数量进行计算的,所以我可以添加尽可能多的独特项目,并且任务数量将扩大以适应它们,绝对不会有重复。我使用它在每天的游戏中跟踪价格,所以它都使用cron作业来解雇,并且根本不需要我的干预。

相关问题