如何在App Engine数据存储上处理每日/每周/每月的电路板?

时间:2010-12-24 00:36:37

标签: google-app-engine

我正在为我的游戏开发一个高分的网络服务,它正在Google App Engine上运行。

我的游戏有5个难度,所以我最初有5个棋盘,每个棋盘都有条目(player_login,得分和时间)。如果玩家提交的分数低于之前的分数,则会被解雇,因此每个玩家只保留最高分。

但为了增加更多的乐趣,我决定包括每日/每周/每月/每年的高分表。所以我为每个难度创建了5个板,使其成为25个板。提交分数后,会将其保存到每个板中,并且应该每天/每周/每月/每年清除这些板。

这是通过调用的cron作业发生的,并删除特定板上的所有条目。

问题出现了:看起来从数据存储中删除条目很慢。从我的测试每日清理看起来删除单个条目大约需要200毫秒。

在最糟糕的情况下,如果游戏非常受欢迎,并且会有10万玩家,而且他们每个人都会在年度董事会中有一个条目,则需要10万* 0.012秒= 12 000秒(3小时!!)清除那块板子。我认为我们可以在App Engine中获得长达30秒的作业,因此这不起作用。

我正在删除following code (thanks to Nick Johnson)

q = Score.all(keys_only=True).filter('b = ',boardToClear)
results = q.fetch(500)
  while results:
    self.response.out.write("deleting one batch;")
    db.delete(results)
    q = Score.all(keys_only=True).filter('b = ',boardToClear).with_cursor(q.cursor())
    results = q.fetch(500)

你建议我怎么处理这个问题?

我想到的一种方法是使用任务队列并删除比每个板中允许的旧分数,即已过期但数量较少的分数。这样我就不会达到一个任务的CPU限制,但是清理不会(几乎)瞬间完成,因此我的12000秒长清理将分成1 200个任务,每个任务大约10秒。

但我认为有些事我做错了,在关系数据库中完成这种操作会快得多。我的数据存储和评分方法可能有问题,因为被锁定在RDBMS思维模式中。

2 个答案:

答案 0 :(得分:4)

首先,提出一些小建议:

  1. 即使您在批处理过程中删除项目,删除每个项目也需要200毫秒吗?最快的删除方法应该是进行keys_only查询,然后立即在整个密钥列表上调用db.delete()
  2. 1.4.0开始,30秒的限制最近放宽到10分钟,用于后台工作(如您正在考虑的cron工作或队列任务)。
  3. 但这些可能无法从根本上解决您的问题。我认为没有办法解决删除大量记录(数十万,比如说)的事实需要一些时间。我不确定这对你的用例来说是一个大问题,因为我可以看到一些有用的技术。

    1. 如您所知,使用任务队列将长时间运行的任务拆分为几个较小的任务。您的用例(删除与特定查询匹配的大量项目)是map-reduce任务的理想选择。 Nick Johnson的blog post on the Mapper API可能对您非常有帮助(因此您不必自己编写所有任务管理代码)。
    2. 您是否需要立即删除所有过时的董事会条目?如果您有一个字段列出特定条目计入的周,月或年,您可以在该字段上编制索引,然后仅在可见的排行榜上显示当前月份的条目。 (毕竟,磁盘空间很便宜。)然后,如果你想慢慢地(超过几小时,比如说,而不是几毫秒)删除过时的数据,你可以在后台执行此操作,而不会有不正确的数据排行榜。

答案 1 :(得分:3)

批量删除实体。虽然单个删除需要相当长的时间(尽管200毫秒似乎非常高),但批量删除不再需要,因为它们会并行删除所有实体。任务队列和cron作业现在可以运行长达10分钟,因此超时不应成为问题。