我想为一款手机游戏构建一个后端,其中包括一个面向所有玩家的“实时”全球领先板,用于使用Google (Python)进行持续一定时间的活动。
一个典型的用法如下:-用户开始并完成一场战斗,获得点(2-5分钟的战斗)-积分在玩家的帐户中积累在事件的持续时间。-玩家可以随时检查主板。-领头羊将返回前10名球员,以及5名球员仅仅在和低于球员的分数。
现在,在实时方面没有真正的限制,板可以每30秒更新一次,每小时更新一次。我希望它是尽可能“快”,而不太贵。
由于我对GAE不太熟悉,所以我想到了这个解决方案:
当我想到这个解决方案时,感觉很“蛮力”。
此解决方案的问题在于所有实体的读和写成本。如果我们以50K活动用户结束,这将意味着对50K+1读取的排序查询,以及50k+1定期写入,这可能非常昂贵(取决于间隔)。
我知道memcache可以阻止一些读和写,但是如果有些实体不在memcache中,那么查询它有意义吗?而且,我也读过,memcache无论如何都可以被刷新,所以除非有一种方法可以廉价地“备份”它,否则它似乎是一个危险的用途,因为数据是相对重要的。
有更简单的方法来解决这个问题吗?
发布于 2014-02-24 06:41:47
你不需要50,000读或5万写。解决方案是在points属性上设置排序顺序。每次更新它时,数据存储都会自动更新它的顺序,这意味着除了points属性之外,您不需要级别属性。因此,你不需要一份工作。
然后,当您需要检索一个领导板时,您需要运行两个查询:一个是针对与用户的点数多或相等的6个实体,另一个是针对较少或相同点数的6个实体。合并结果,这就是您要向用户显示的内容。
至于您的前10位查询,您可能希望将其结果放在Memcache中,其过期时间为5分钟。当您需要它时,首先检查Memcache。如果未找到,请运行查询并更新Memcache。
编辑:
若要澄清查询部分,请执行以下操作。您需要设置排序顺序和不等式筛选器的正确组合,以获得所需的结果。根据App文档,查询按以下顺序执行:
因此,对于一个查询,您需要将升序顺序与GREATER_THAN_OR_EQUAL过滤器相结合,对于另一个查询,则需要将降序顺序与LESS_THAN_OR_EQUAL过滤器相结合。在这两种情况下,您都将检索结果的限制设置为6。
还要注意:您将限制在6个实体,因为这两个查询都将返回用户本身。您可以添加另一个过滤器(userId NOT_EQUAL到您的用户id),但是我不推荐它--成本不值得节省。显然,不能对点使用大于/小于__过滤器,因为许多用户可能有相同的点数。
发布于 2014-08-19 18:07:14
发布于 2014-02-24 05:01:14
这是否简单是值得商榷的。
我认为排名不仅仅是排序积分的问题,在这种情况下,这只是一个简单的查询。我的排名涉及到其他因素,而不仅仅是目前的分数。
我会考虑为用户每次更新点数(实际上是一个队列)编写一个事件记录。任务运行收集所有当前事件记录,此外,还维护一组表示领导板顶部的记录。根据传入的事件记录调整这组记录。一旦处理,丢弃事件记录。这将限制您在小时间窗口中只对活动事件进行读写。领导委员会可能是一个单一的实体,由密钥获取并缓存。
我假设您可能有不同的排名方案,如当前的活动等级(针对当前的7天),和所有的时间级别。(一段时间不打球的球员)。
当玩家查看他们的排名时,您可以使用两个简单的查询-- Players.query(Players.score > somescore).fetch(5)
和Players.query(Players.score < somescore).fetch(5)
--这不应该花费太多,您可以缓存它们。
https://stackoverflow.com/questions/21979038
复制相似问题