编辑:看我的回答。问题出在我们的代码上。MR工作正常,它可能有状态报告问题,但至少输入阅读器工作正常。
我现在运行了一个实验几次,我现在确定mapreduce(或DatastoreInputReader)有奇怪的行为。我怀疑这可能与键范围和分割键范围有关,但这只是我的猜测。
无论如何,这是我们的设置:
- 在创建新实体时,我们有一个名为"AdGroup"的NDB模型我们使用从AdWords返回的相同id(它是一个整数),但我们使用它作为字符串:
- 我们的数据存储中有1,163,871个这样的实体"数据存储管理"页面告诉我们——我知道不完全是这样准确的数字,但我们不经常创建/删除adgroups,所以我们可以肯定地说,这个数字是110万或更多)。
mapreduce是这样启动的(从另一个管道):
yield mapreduce_pipeline.MapreducePipeline( job_name='AdGroup-process', mapper_spec='process.adgroup_mapper', reducer_spec='process.adgroup_reducer', input_reader_spec='mapreduce.input_readers.DatastoreInputReader', mapper_params={ 'entity_kind': 'model.AdGroup', 'shard_count': 120, 'processing_rate': 500, 'batch_size': 20, }, )
AdGroup(id=str(adgroupId))
如果我错了请纠正我,但考虑到我使用非常基本的DatastoreInputReader - mapper-调用应该等于实体的数量。所以应该是110万或更多。
注意:我首先注意到这个问题的原因是因为我们的营销人员开始抱怨"我们添加了新的广告组已经4天了,他们仍然没有出现在你的应用程序中!"。
现在,我只能想到一个解决方案-将所有adgroups的所有键写入blobstore文件(每行一个),然后使用BlobstoreLineInputReader。当然,写入blob部分必须以不利用DatastoreInputReader的方式进行。我现在就用这个,还是你有更好的建议?
注意:我也试过用相同的代码使用DatastoreKeyInputReader -结果是相似的- mapper调用在450,000和550,000之间。
最后是问题。如何为实体生成id很重要吗?使用int
id比str
id更好吗?一般来说,我该怎么做才能让mapreduce更容易找到映射它们的所有实体?
PS:我还在试验中,以后可能会添加更多细节。
经过进一步调查,我们发现错误实际上是在我们的代码中。因此,mapreduce实际上按预期工作(每个数据存储实体都调用mapper)。
我们的代码正在调用一些google服务函数,这些函数有时失败(奇妙的神秘的ApplicationError消息)。由于这些失败,正在重试MR任务。但是,我们对任务队列重试设置了限制。MR既没有检测到也没有以任何方式报告这一点——MR在所有分片的状态页上仍然显示"成功"。这就是为什么我们认为我们的代码一切正常,只是输入阅读器出了问题。