Google App Engine 数据存储区中每秒写入 5 次以上的事务计数器

Posted

技术标签:

【中文标题】Google App Engine 数据存储区中每秒写入 5 次以上的事务计数器【英文标题】:Transactional counter with 5+ writes per second in Google App Engine datastore 【发布时间】:2010-12-19 16:55:40 【问题描述】:

我正在开发一款游戏的锦标赛版本,我希望同时有 1000 多名玩家参与其中。比赛开始时,玩家会很快被淘汰(可能每秒超过 5 个),但随着比赛的进行,这个过程会减慢。根据玩家在比赛中被淘汰的时间,会获得一定数量的积分。例如,第一个掉线的玩家一无所获,而第 500 位的玩家获得 1 分,而第一名的玩家获得 200 分。现在我想在玩家被淘汰后立即奖励并显示积分数。

问题是,当我在玩家被淘汰后将新行推入数据存储区时,行实体必须位于单独的实体组中,因此我不会达到每秒 1-5 次写入的 gae 数据存储区限制对于 1 个实体组。此外,我需要能够一致地读取和写入行数,以便为所有被淘汰的玩家正确确定奖品。

实现数据模型以支持这一点的最佳方式是什么?

【问题讨论】:

是否有联系,或者结果是严格的全序集?游戏的总持续时间是多少,或者换句话说,玩家将如何完成游戏?游戏完成是否遵循指数分布、均匀分布、正态分布或 beta 分布? 没有关系。比赛在只剩下一名玩家时结束,并且必须始终有严格的淘汰顺序。奖池分配将在比赛开始时计算。想想德州扑克锦标赛。 在德州扑克锦标赛中,当多人全押时,牌桌会转为手牌游戏 - 否则,将无法确定谁真正先出局两张桌子或多或少同时消除了人。 【参考方案1】:

由于玩家数量有限,几秒钟内的争用问题不太可能持续很长时间,因此您有两种选择:

    直接忽略这个问题。会出现一连串消除,但只要不是持续的情况,事务的重试机制将确保它们都被执行。 当有人外出时,独立记录这一点,并异步更新锦标赛状态、分配排名。这意味着您不能立即通知他们他们的排名,而是需要做出异步回复或让他们轮询。

坦率地说,我建议前者:即使你的 1000 人锦标赛在前 5 分钟内结束了一半——这是一个极其不可能的事件——你仍然看到每秒少于 2 次淘汰。实际上,任何尖峰都会比这更小且寿命更短。

要记住的一点是,由于事务重试的工作方式,同一实体组上一起发生的事务将以半随机顺序解决 - 也就是说,它不是严格的 FIFO 队列。如果您需要,您必须自己执行,尽管在任何类型的分布式系统中这都不是一件容易的事。

【讨论】:

谢谢尼克,很高兴见到你 :) 我现在会选择第一个选项,但为了将来的参考,也许对于其他可能有类似问题的人来说,现在假设我'我会选择选项 2。我会在每次玩家被淘汰时插入一行,然后异步任务会不时地分配排名并将这些行移动到锦标赛实体中的集合中。你将如何运行异步任务来做到这一点?我可能会使用带有 memcache 的任务队列来确保 1 场锦标赛的任务每秒排队不会超过一次。 @jaz 使用命名任务,以它们执行的时间间隔命名。【参考方案2】:

现有的 cmets 和答案很好地解决了具体问题。

在更高的层次上,看看这个来自 google Code jam 团队的post and open source library。他们遇到了类似的问题,最终开发了一个基于数据存储的可扩展记分板,可以有效地处理任意页面的更新和请求。

【讨论】:

以上是关于Google App Engine 数据存储区中每秒写入 5 次以上的事务计数器的主要内容,如果未能解决你的问题,请参考以下文章

在 Google App Engine 上的数据存储区中更新大量实体

计算在 Google App Engine 数据存储区中计算分数和日期的索引

Google App Engine 数据存储区中每秒写入 5 次以上的事务计数器

在“编译”时不知道属性名称的情况下,在 Python 中复制 Google App Engine 数据存储区中的实体

将来自 Android 应用程序的数据存储在 App Engine 数据存储区中

put() 后 App Engine 数据存储区中的读取延迟