我正在尝试了解谷歌i / o上提供的数据管道谈话: http://www.youtube.com/watch?v=zSDC_TU7rtc
如果我打算通过输入序列标记进行批处理,我不明白为什么需要使用扇入工作索引。
乐观排队的任务不能抓住所有未应用的标记,通过尽可能多的标记(重复获取一批10个,然后事务更新物化视图实体),并在任务中重新入队自己在完成所有标记之前超时?
工作索引是否与查询所有未应用标记的效率有关?也就是说,最好查询“带有work_index =的标记”而不是“带有apply = False的标记”?如果是这样,为什么会这样?
作为参考,引导我进行数据管道谈话的问题+答案在这里: app engine datastore: model for progressively updated terrain height map
答案 0 :(得分:6)
一些事情:
我的方法假设多个工作者(请参阅ShardedForkJoinQueue here http://code.google.com/p/pubsubhubbub/source/browse/trunk/hub/fork_join_queue.py),其中任务的入站速率超过单个线程可以执行的工作量。考虑到这一点,你将如何使用一个简单的“applied = False”来分割N个线程的工作?可能会随机将模型上的另一个字段分配给worker的shard_number;那么你的查询将是“shard_number = N AND applied = False”(需要另一个复合索引)。好的,这应该有效。
但是你怎么知道你需要多少个工作分片/线程呢?使用上面的方法,您需要静态配置它们,以便您的shard_number参数介于1和N之间。您一次只能有一个线程查询每个shard_number,否则您会有争用。我希望系统在运行时找出分片/线程数。我的方法将一起工作分成合理大小的块(如10个项目),然后将连续任务排入队列来处理其余的事情。使用查询游标我知道每个延续都不会与最后一个线程重叠,因此没有争用。这为我提供了一个动态数量的线程,它们在同一个分片的工作项上并行工作。
现在说你的队列备份了。您如何确保首先处理最早的工作项?换句话说:你如何防止饥饿?您可以将模型上的另一个字段分配给插入时间 - 将其命名为add_time。现在您的查询将是“shard_number = N AND applied = False ORDER BY add_time DESC”。这适用于低吞吐量队列。
如果您的工作项目写入率上升了一下怎么办?你将要编写许多行,并使用大致相同的add_time。这需要您的实体的Bigtable行前缀,如“shard_number = 1 | applied = False | add_time = 2010-06-24T9:15:22”。这意味着每个工作项插入都会击中相同的 Bigtable平板电脑服务器,该服务器当前是降序索引的词汇头的所有者。因此,从根本上说,您只能为每个工作分片的数据存储区写入单个机器的吞吐量。
使用我的方法,您唯一的Bigtable索引行以递增工作序列号的哈希为前缀。每次序列号递增时,此work_index值分散在Bigtable的词法行空间中。因此,每个顺序工作项排队可能会转到不同的平板电脑服务器(给定足够的数据),将我的队列负载分散到一台机器上。使用这种方法,写入速率应该只受到集群中物理Bigtable机器数量的限制。
答案 1 :(得分:2)
这种方法的一个缺点是需要额外写入:当您完成更新时,您必须在原始标记实体上翻转标记,这是Brett原始方法不需要的。
你仍然需要某种工作索引,或者你遇到Brett谈到的竞争条件,应用更新的任务在更新事务提交之前运行。在您的系统中,更新仍然会得到应用 - 但在下次更新运行并应用它之前可能是一段任意时间。
尽管如此,我还不是这方面的专家(还有)。我已经把你的问题转发给了布雷特,我会让你知道他说的话 - 我也很好奇他的回答!