没有分片的高并发计数器

时间:2010-05-05 00:57:07

标签: python google-app-engine counter

这个问题涉及两个计数器的实现,这些计数器的目的是在没有分片的情况下进行扩展(在某些情况下可能会计算得不足):

  1. http://appengine-cookbook.appspot.com/recipe/high-concurrency-counters-without-sharding/(评论中的代码)
  2. http://blog.notdot.net/2010/04/High-concurrency-counters-without-sharding
  3. 我的问题:

    • 关于#1:在延迟的交易任务中运行memcache.decr()似乎有点矫枉过正。如果memcache.decr()在事务之外完成,我认为最坏的情况是事务失败,我们错过了计算我们减少的数量。 我是否忽略了这样做可能导致的其他问题?
    • 两种实现之间有何重大权衡?

    以下是我看到的权衡:

    • 2不需要数据存储区事务。

    • 要获取计数器的值,#2需要数据存储区提取,而#1 通常只需要执行memcache.get()memcache.add()
    • 递增计数器时,都会调用memcache.incr()。 #2会定期向任务队列添加任务,而#1以事务方式执行数据存储区get和put。 #1也始终执行memcache.add()(以测试是否是将计数器持久保存到数据存储区的时间)。

    结论

    (没有实际运行任何性能测试):

    • 1通常应该更快地检索计数器(#1 memcache vs#2数据存储区)。虽然#1也必须执行额外的memcache.add()

    • 但是,更新计数器时#2应该更快(#1数据存储区get + put vs#2排队任务)。
    • 另一方面,对于#1,您必须对更新间隔更加小心,因为任务队列配额几乎比数据存储区或memcahce API小100倍。

2 个答案:

答案 0 :(得分:1)

转到数据存储区可能比通过memcache更昂贵。其他memcache首先不会有用: - )

我推荐第一个选项。

如果您有合理的请求率,您实际上可以更简单地实现它:

1) update the value in memcache
2) if the returned updated value is evenly divisible by N
2.1) add N to the datastore counter
2.2) decrement memcache by N

这假设您可以在memcache上设置足够长的超时以在连续事件之间生存,但是如果事件非常稀疏以至于memcache超时,则可能不需要“高并发”计数器: - )< / p>

对于较大的网站,依靠单个内存缓存来执行计算总页面点击数等操作可能会让您遇到麻烦;在这种情况下,你真的想要对你的memcaches进行分片,并更新一个随机的计数器实例;计数器的聚合将通过数据库更新发生。

但是,在使用memcache时,请注意某些客户端API会假定一秒钟超时意味着该值不存在。如果到memcache实例的TCP SYN数据包被丢弃,这意味着您的请求将错误地假设数据不存在。 (对于memcache,UDP可能会发生类似的问题)

答案 1 :(得分:-2)

Memcache得到满脸通红,你失去了你的柜台。哎哟。使用mysql数据库或NOSQL解决方案将解决该问题,可能会遇到性能损失。 (Redis,Tokyotyrant,MongoDB等......)可能没有那种性能影响。

请记住,您可能需要执行两项操作:

  1. 为了高性能原因,请保留一个memcache计数器。
  2. 保留日志,然后从中获取更准确的指标。