如何并行更新400,000个GAE数据存储区实体?

时间:2014-02-07 21:58:47

标签: java google-app-engine parallel-processing google-cloud-datastore

我有400,000个特定类型的实体,我想对每个实体执行一个简单的操作(添加属性)。我不能连续处理它们,因为它需要永远。我不想使用MapReduce库,因为它很复杂而且势不可挡。

基本上我想在任务队列上创建100个任务,每个任务占用大约4,000个实体,并在每个任务上执行此操作。希望当所有任务并行执行时,处理所有400k实体的时间不会超过几分钟。

但是,我不确定如何使用GAE查询来执行此操作。我的实体的字符串ID为“230498234-com.example”,由我的应用程序生成。我希望每个任务基本上都要向数据存储区询问“请给我实体#200,000-#204,000”,然后逐个操作它们。

这可能吗?如何以这种方式划分数据存储?

4 个答案:

答案 0 :(得分:5)

这是MapReduce(https://developers.google.com/appengine/docs/python/dataprocessing/)的完美工作。一开始可能很难学,但一旦掌握,你就会爱上它。

您还可以考虑在下次保存条目时懒惰添加属性,前提是该属性与查询中的默认值不同。

答案 1 :(得分:4)

阅读速度快,写作速度慢。除非您可以进行有效的查询来分割数据(提示:不要使用偏移分页,因为appengine会将索引一直遍历到每个页面的页面,而是使用查询游标),让一个后端执行单个查询,将要处理的数据发送到任务队列。例如,每个可以处理100个。 这里的优点是您不需要对数据进行分段,除了启动单个后端以创建任务队列时,您不需要任何复杂的设置,因为它从单个查询中读取。新的appengine模块可能比标准的后端实例更容易(因为它们不会随机停止)。

如果要使其非常健壮,请使用带有pagesize = elements的查询游标来处理每个任务队列并记住您创建任务队列的最后一个游标。如果后端在完成再次启动之前停止,它将在停止的地方继续运行。

答案 2 :(得分:0)

任务主机可以执行查询并将游标(使用“结束游标”)发布到任务队列,每个队列对应1k结果,而不是获取结果。请注意,无法保证工作人员在光标上执行时会看到完全相同的查询结果,但这可能已经足够了。具有更多保证的替代方案是在任务主机上执行仅密钥搜索并实际获取结果(密钥),然后将1000组发布到任务队列。工作人员可以使用multiget来检索具有更强一致性保证的项目。

答案 3 :(得分:0)

我第一次使用mapreduce几乎就是这样的。我必须在我的图像模型中添加一个属性,我这样做了:

在mapreduce.yaml

mapreduce:
- name: cleanimages
  mapper:
    input_reader: mapreduce.input_readers.DatastoreInputReader
    handler: main.process
    params:
    - name: entity_kind
      default: main.Image

然后你想要发生什么,你输入了process代码:

def process(entity):
    entity.small = None
    yield op.db.Put(entity)

在这种情况下,我只是将其中一个变量设置为None,因为它已不再使用,但您可以在其中放置任何代码,创建新属性并保存实体,如abose。您可以在mapreduce site找到更多信息。