Google App Engine计数器

时间:2010-10-03 14:41:38

标签: python google-app-engine transactions google-cloud-datastore

对于GAE数据存储区中的所有数据,我有一个用于跟踪计数器/记录总数的模型(因为我们不能使用传统的SUM查询)。每当我插入/删除记录时,我想知道增加这些全局计数值的最有效方法。这就是我目前正在做的事情:

counter = DBCounter.all().fetch(1)
dbc = DBCounter(totalTopics=counter[0].totalTopics+1)
dbc.put()

但这对我来说似乎很草率。有关更好的方法的任何想法吗?

2 个答案:

答案 0 :(得分:5)

您的方法存在一些问题:

  • 由于您不使用事务以原子方式更新计数器,因此可能计数不足。
  • 效率低下:
    • 如果您需要经常更新此计数器,争用可能会成为问题。由于您只有一个计数器,因此无法很好地扩展。数据存储区实体只能以每秒最多5次的速率写入。
    • 每次插入记录时,您都要写入数据存储区两次。如果您最终使用事务来解决上述问题,那么每次插入记录时(每次插入一次,一次更新计数器),您将对数据存储区进行两次往返。您可以使用一种避免额外往返数据存储区的方法。

以下是一些替代方法(从最不准确[和最快]到最准确[和最慢]):

  • 如果您只需要粗略计算数据存储区中特定类型的实体数量,那么您可以使用Stats API。但是,您检索的计数不会不断更新。
  • 如果您需要更多的粒度,但是偶尔计算不足的可能性很小,那么您可以使用内存缓存增强计数器。在this question中讨论了几个很好的实现。请特别注意this recipe中的评论中的代码。
  • 如果你真的想避免计算不足,那么你应该考虑一个sharded datastore counter。这将从上面消除争用问题。

答案 1 :(得分:4)

如果你需要在计算时保持可扩展性,你应该查看Joe Gregorio关于sharding counters和DocSavage implementation这个想法的文章。

AppEngineFan的优秀博客也提供有关可扩展非分片计数器的信息,请参阅使用任务队列的this one并指向上一篇关于使用cron作业的文章。