Google App Engine 计数器

2 投票
2 回答
1048 浏览
提问于 2025-04-16 04:56

我在GAE数据存储中有一个模型,用来记录计数器和总记录数(因为我们不能使用传统的SUM查询)。我想知道在插入或删除记录时,最有效的方式来增加这些全局计数值。现在我正在做的是:

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

但我觉得这样做有点不太好。有没有更好的方法呢?

2 个回答

5

你的方法有几个问题:

  • 可能会出现低估的情况,因为你没有使用事务来原子性地更新计数器。
  • 效率不高:
    • 如果你需要频繁更新这个计数器,竞争可能会成为一个问题。因为你只有一个计数器,这样的做法不太适合扩展。数据存储的实体每秒最多只能写入5次。
    • 每次插入记录时,你都要向数据存储写入两次。如果你使用事务来解决上面的问题,那么每次插入记录时就要进行两次往返(一次插入,一次更新计数器)。你可以考虑一种方法,避免这额外的往返。

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

  • 如果你只需要大致了解数据存储中特定类型实体的数量,可以使用统计API。不过,你获取的计数不是实时更新的。
  • 如果你需要更精确的计数,但可以接受偶尔低估的可能性,可以使用增强的内存缓存计数器。在这个问题中讨论了几种不错的实现。特别是,可以查看这个食谱中的评论代码。
  • 如果你真的想避免低估,那么可以考虑使用分片数据存储计数器。这样可以消除上面提到的竞争问题。
4

如果你想在计数的时候保持可扩展性,可以看看Joe Gregorio写的关于分片计数器的文章,还有DocSavage对这个想法的实现

AppEngineFan的优秀博客里也有关于可扩展的非分片计数器的信息,看看这篇文章,它使用了任务队列,并提到了之前关于使用定时任务的文章。

撰写回答