这本身不是一个应用引擎问题…尽管我们的应用程序在App-Engine上使用NDB对数据存储运行。所以这个问题是关于在分布式系统中处理大型数据集的。
我们有一个不断增长的数据集,我们需要计算统计数据(计数,总和等)。我们有一些系统能够以不同的方式成功地做到这一点,以便在事情发生变化时进行事务性维护……但有些情况下,我们想要抛弃我们的统计数据,从头开始重新计算它们……或者运行验证例程来检查我们一直保持差异的计数/总数
问题是,一般来说,在分布式系统中针对不断变化的大型数据集构建统计数据的最佳实践是什么?
假设我们启动了一个大型的MapReduce作业来对一百万个实体上的特定字段求和…当该作业运行时,有几个新实体进入,几个被删除,还有几个求和属性发生了变化。有哪些最著名的/被接受的/成功的方法来确保这些添加/删除/更改能算进总收益中?
我这样做的方式是,我不查询所有的实例,并运行我的操作在所有他们每次。我有一个单独的实体组来处理1个属性中的这些统计信息。每当我创建/更新一个实例时,我都会相应地更新这个属性的值,当我删除一个实例时,我也会相应地更新这个值。
确保任何更新都更新统计实体组的最佳方法是使用钩子,这些钩子将在每次添加或删除实例时自动运行。
希望对你有帮助。
如果您能够满足以下几个条件:
- 跟踪每个MapReduce子作业
- 确定结果将受到事务更新影响的单个MapReduce子作业
- 确保这些受影响的MapReduce子作业不会与影响它们的事务更新同时运行(可能由事务本身确保?)
- 确定在事务更新中,对于每个干扰MapReduce子作业,子作业是否已经完成
然后你可以为每个已经完成的干扰子作业生成和应用不同的统计更新(可能在整个大型MapReduce作业完成后应用它们?)尚未执行的子作业不需要这样的差异统计,因为当子作业在其上执行时,内容将已经更新。
您可能需要单独处理事务更新中添加、删除和普通更改的干扰。
或者,您可以存储所有MapReduce子作业的部分结果,跟踪其中哪些受到事务性更新的影响(如果有的话),并在大型MapReduce作业结束时检查作业运行时是否发生了任何更新。如果是这样,只需重新运行受影响的子作业以获得更新的部分结果,并将部分结果重新组装到最终结果中。重复,直到没有更新发生,而最近的部分MapReduce重新运行正在进行中。或多或少的rsync
风格,以最小的停机时间复制/移动大型活动分区。
您甚至可以从事务更新向映射器提供相关的影响信息(稍微聪明一点的),让映射器自己评估对可能受影响的映射的影响,并相应地传播信息,以便在更新进来时重新运行受影响的子作业:)