如何处理 fork-join-queue 中的最终一致性

How to deal with eventual consistency in fork-join-queue

我目前正在寻找替换以下视频中描述的有缺陷的 fork-join-queue 实现:

https://youtu.be/zSDC_TU7rtc?t=33m37s

我知道这个视频已经有将近八年的历史了,我很乐意学习任何潜在的新的和更好的方法来做这些事情,但现在我正专注于努力使这个工作正如布雷特所描述的那样。目前,摆在我面前的有点乱。

原始开发人员与 Brett 不同的地方之一是,他将特定 sum_name 的所有工作项放入单个实体组中。

我对数据存储还比较陌生,但对我来说这似乎违背了整个目的,因为每秒多次向实体组添加新实体会引起争用,而这正是我们重新尝试通过批处理更改来避免。

至于为什么有人会尝试将所有工作放在一个实体组中,原开发者的评论很明确——他试图防止工作项目因到期而被跳过到最终一致性。这让我真正深入研究了 Brett 的实现,我很困惑,因为这似乎是 Brett 没有考虑到的问题。

简而言之,当 Brett 的任务查询工作项时,它使用的索引可能不是最新的。当然,他对 memcache 所做的锁定应该使这不太可能,因为任务的开始将阻止更多的工作项被添加到该索引。但是,如果索引更新时间足够长以至于在锁递减之前写入了一些内容,但查询结果中仍然没有返回怎么办?这样的工作项不会只是挂在数据存储中,永远不会被使用吗?

Brett 的实施中是否有我没有看到的处理此问题的某些方面?显然Brett知道自己在做什么,并且对此非常有信心,所以我觉得我一定错过了什么。

但是,如果没有,人们可能会如何处理这个问题?

我认为关于散列的一点是他如何避免这种情况,'Distribute the load across Bigtable' 并避免来自 'writing to the beginning of the same row' 的所有工作条目:https://youtu.be/zSDC_TU7rtc?t=48m40s

即使不是这样,他对 Datastore 内部运作的部落知识似乎也在这里发挥了作用。

您可以让您的任务启动另一个任务,该任务会在 10 秒后执行完整性检查。

他实际上确实提到如果您有 'lossy data model' https://youtu.be/zSDC_TU7rtc?t=48m40s

,则让离线作业收集任何丢失的数据

根据演讲日期,演讲采用了 master/slave 数据存储。谈话是从 2010 年开始的,但是高复制 Datastore (https://googleappengine.blogspot.com/2011/01/announcing-high-replication-datastore.html) 直到 6 个月后才发布。

解决实体组争用的一种方法是使用 task-name-INDEX 之类的内容手动创建工作项密钥,并在任务中获取从 task-name-0 到 task-name-TOP_INDEX 和 top 索引大概可以存储在 memcache 中。