在 Google App Engine 中保持一致计数
Keeping Consistent Count in Google App Engine
我正在寻找有关 Google App Engine 平台上一个非常常见问题的建议,以保持一致的计数器。
我有一个任务来加载域的组,然后为每个组创建一个任务以将其组成员加载到一个单独的任务中。现在由于有成千上万的组和成员,任务太多了。
我将创建一个任务来获取一页组,在该任务中我将为每个组创建多个任务以获取其 members.Now,以了解我是否已加载所有组,我有逻辑来只需检查 nextPageToken,然后将组加载标志设置为完成。
然而,由于每个组都有单独的任务来加载成员,我需要跟踪所有组成员任务是否已完成。现在我遇到一个问题,即访问单个 numGroupMembersFinished 计数的各种任务会产生并发问题,并且计数会在某处损坏而不是 return 正确的数据。
我的回答很笼统,因为你的问题没有任何代码或建议的解决方案,因为你没有说你打算在哪里保留那个柜台。
网络上的许多文章都涵盖了这一点。 Google for "sharding counters" 用于在 O(1) 时间内快速计算数据存储实体的半可扩展方式。
更重要的是查看内存缓存 api。它具有以原子方式 increment/decrement 存储在那里的计数器的功能。那个保证永远不会有并发问题但是你仍然需要一些方法来恢复 and/or 仔细检查内存缓存条目没有被驱逐,也许还可以将计数保存在你异步设置的实体中并且"get by key" 始终获取其最新值。
这仍然不是 100% 防弹的,因为缓存可能会在您同时尝试修改它的同时被逐出,因此您的备份数据存储实体可能会错过 "set"。
您需要根据预期的并发使用情况来计算错过 increment/decrement 的机会是否大于彗星撞击地球的机会。希望你不会在空中交通管制员身上使用它。
您可以使用 MapReduce 或管道 API:
https://github.com/GoogleCloudPlatform/appengine-mapreduce
https://github.com/GoogleCloudPlatform/appengine-pipelines
允许您将问题拆分为更小的可管理部分,从而库可以处理任务之间 signaling/blocking 的所有细节,收集结果,并在完成后将它们交还给您
Google I/O 2010 - Google App Engine 的数据管道:
https://www.youtube.com/watch?v=zSDC_TU7rtc
Google I/O 2011:使用 App Engine 管道进行大规模数据分析 API:
https://www.youtube.com/watch?v=Rsfy_TYA2ZY
Google I/O 2011:应用引擎 MapReduce:
https://www.youtube.com/watch?v=EIxelKcyCC0
Google I/O 2012 - 在 Google 规模上构建数据管道:
Zig Mandel 提到过,这是 link 到 Google 自己实现计数器的秘诀:
https://cloud.google.com/appengine/articles/sharding_counters
我将可配置的分片计数器复制粘贴(重命名了一些变量等...)到我的应用程序中并且运行良好!
我使用了本教程:https://cloud.google.com/appengine/articles/sharding_counters 和 hashid 库并创建了这个 golang 库:
https://github.com/janekolszak/go-gae-uid
gen := gaeuid.NewGenerator("Kind", "HASH'S SALT", 11 /*id length*/)
c := appengine.NewContext(r)
id, err = gen.NewID(c)
同样的方法对于其他语言应该很容易。
我正在寻找有关 Google App Engine 平台上一个非常常见问题的建议,以保持一致的计数器。 我有一个任务来加载域的组,然后为每个组创建一个任务以将其组成员加载到一个单独的任务中。现在由于有成千上万的组和成员,任务太多了。 我将创建一个任务来获取一页组,在该任务中我将为每个组创建多个任务以获取其 members.Now,以了解我是否已加载所有组,我有逻辑来只需检查 nextPageToken,然后将组加载标志设置为完成。
然而,由于每个组都有单独的任务来加载成员,我需要跟踪所有组成员任务是否已完成。现在我遇到一个问题,即访问单个 numGroupMembersFinished 计数的各种任务会产生并发问题,并且计数会在某处损坏而不是 return 正确的数据。
我的回答很笼统,因为你的问题没有任何代码或建议的解决方案,因为你没有说你打算在哪里保留那个柜台。
网络上的许多文章都涵盖了这一点。 Google for "sharding counters" 用于在 O(1) 时间内快速计算数据存储实体的半可扩展方式。
更重要的是查看内存缓存 api。它具有以原子方式 increment/decrement 存储在那里的计数器的功能。那个保证永远不会有并发问题但是你仍然需要一些方法来恢复 and/or 仔细检查内存缓存条目没有被驱逐,也许还可以将计数保存在你异步设置的实体中并且"get by key" 始终获取其最新值。
这仍然不是 100% 防弹的,因为缓存可能会在您同时尝试修改它的同时被逐出,因此您的备份数据存储实体可能会错过 "set"。
您需要根据预期的并发使用情况来计算错过 increment/decrement 的机会是否大于彗星撞击地球的机会。希望你不会在空中交通管制员身上使用它。
您可以使用 MapReduce 或管道 API:
https://github.com/GoogleCloudPlatform/appengine-mapreduce https://github.com/GoogleCloudPlatform/appengine-pipelines
允许您将问题拆分为更小的可管理部分,从而库可以处理任务之间 signaling/blocking 的所有细节,收集结果,并在完成后将它们交还给您
Google I/O 2010 - Google App Engine 的数据管道:
https://www.youtube.com/watch?v=zSDC_TU7rtc
Google I/O 2011:使用 App Engine 管道进行大规模数据分析 API:
https://www.youtube.com/watch?v=Rsfy_TYA2ZY
Google I/O 2011:应用引擎 MapReduce:
https://www.youtube.com/watch?v=EIxelKcyCC0
Google I/O 2012 - 在 Google 规模上构建数据管道:
Zig Mandel 提到过,这是 link 到 Google 自己实现计数器的秘诀:
https://cloud.google.com/appengine/articles/sharding_counters
我将可配置的分片计数器复制粘贴(重命名了一些变量等...)到我的应用程序中并且运行良好!
我使用了本教程:https://cloud.google.com/appengine/articles/sharding_counters 和 hashid 库并创建了这个 golang 库:
https://github.com/janekolszak/go-gae-uid
gen := gaeuid.NewGenerator("Kind", "HASH'S SALT", 11 /*id length*/)
c := appengine.NewContext(r)
id, err = gen.NewID(c)
同样的方法对于其他语言应该很容易。