如何在交易中做柜台? (分片计数器)

时间:2011-08-17 08:20:40

标签: java google-app-engine

我读过this但仍然无法得到它。 我想做的是一家书店。 有很多书籍对象,每本书有两个柜台。 一个计数器是记录喜欢它的人数。 另一个是记录讨厌它的人数。 显然,我需要在交易中增加计数器,以防超过5个人同时喜欢或讨厌一本书,对吗?

我的问题是:
1.如何在同一实体组中制作书籍和计数器,以便我可以在同一交易中使用它们 2.如何实现分片计数器?我不明白为什么(第三个例子中here)我们需要ShardedCounter,Counter和GeneralCounterShard以及如何使用它们?
谁能举个例子吗?我正在使用JDO。

感谢您的任何建议!

3 个答案:

答案 0 :(得分:2)

你是否真的害怕超过5人在同一秒内更新同一本书的柜台?这将是您的应用程序的巨大流量的标志。如果是这样,你可能会遇到更重要的问题而不是一个计数器可能被一两票投票的事实。

我只是让计数器成为Book实体的一部分:

public class Book {
    // ...
    private int numberOfLovers;
    private int numberOfHaters;
    // ...
}

保持简单,当且仅当您遇到问题时才更改设计。

答案 1 :(得分:1)

我们在AppEngine / Python上驱动了相当繁重的缓存应用程序(即每天超过200,000个请求,峰值高达每秒60次),我们必须计算所有内容(例如请求,字节输入,字节输出)。

你的问题似乎不那么极端;但是,我们发现的解决方案也比你提到的解决方案(以及我们已经读过的)更简单:我们将计数器存储在Memcache中,并在需要的地方使用其“incr()”函数。

由于Memcache透明地管理分片,你不必考虑它。

然后,每分钟触发一次cron请求以获取值,将它们存储在数据存储区中,并通过调用Memcache“decr()”函数按检索到的值递减计数器。

以这种方式,获取和减少之间发生的增量不会丢失,并将在下一分钟处理。

当然Memcache中断是一个问题,但它们并不经常发生。

答案 2 :(得分:0)

如果您需要在一个事务中更新少数元素,则实体组很有用。 例如,从一个实体计数器递减值,在另一个实体计数器递增。并且需要确保这些或两个操作都已完成,或者都不是。

由于您只需要增加一个值(或来自相同实体的两个值),您不需要任何组。

只需在交易中更新您的实体即可。 GAE事务使用乐观锁定,这意味着以下步骤:

  1. 您从db获取当前值(例如按键)
  2. 设置任何字段的值
  3. 更新实体
  4. 并且,在将实体保存到数据库时,gae会检查自第一次读取后该实体是否未更新(请参阅步骤1)。如果它仍然相同 - 它会保存您的新值。如果它改变了 - 它抛出异常。就是这样。

    如果您有例外 - 您可以重新加载实体,并尝试再次更新。