App-Engine中的原子计数器增量

时间:2015-10-05 21:18:17

标签: google-app-engine google-cloud-endpoints google-cloud-datastore objectify

我仍然对交易感到困惑,无论是使用DatastoreService还是Objectify。 (是的,我读过What is the correct way to atomically increment a counter in App Engine?)。我需要原子地增加一个计数器。我怎么做? app引擎文档中的示例在finally块中有回滚。但是我不希望回滚,我希望系统继续尝试。另一方面,客体文档说它的交易模型与低级API不同。所以我正在编写这两个代码,我只需要帮助纠正它们或确认它们。

DatastoreService版本

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService()
Transaction txn = datastore.beginTransaction();
try {
    Key commentKey = KeyFactory.createKey(“Comment”, id);
    Entity comment = datastore.get(commentKey);
    int views = (Integer)comment.getProperty(“views”);
    views++;//increment step
    comment.setProperty(“views”, views);

    datastore.put(comment);

    txn.commit();
} finally {
    if (txn.isActive()) {
        txn.rollback();
    }
}

客观化版本

ofy().transact(new VoidWork() {

      @Override
      public void vrun() {
        Comment comment = ofy().load().type(Comment.class).id(commentId).now();
        long views = 1+ comment.getViews();
        comment.setViews(views);
        ofy().save().entity(comment).now();
      }
    });

重要的一点是,我希望系统不断尝试无限制。当然,我希望客户端调用返回,而所有这些都是异步发生的。谢谢你的帮助

1 个答案:

答案 0 :(得分:1)

如果存在并发冲突,Objectify版本将重试。您可以修改DatastoreService版本以循环ConcurrentModificationException,您将获得相同的逻辑。

然而,这并不能让你得到一个非常准确的计数器(尽管它通常足够接近大多数用途)。但是,您不希望像这样运行银行交易。

问题(存在于所有分布式事务处理系统中)是在事务期间出现问题,例如,抛出DatastoreException。这使您的计数器处于不确定状态 - 提交是否成功?你不知道。

如果你想要准确(并且你确实说非常准确),你需要执行一些变化:

  1. 在开始交易之前使用唯一键创建一个txn记录
  2. 开始交易
  3. 检查记录是否存在;如果没有,你已经完成了
  4. 删除记录,递增计数器,然后提交
  5. 如果错误,请从2开始重复直至成功
  6. 并且您需要某种查询来清除完全失败的事务的剩余txn记录。

    这种变化是在事务之前创建id,并在事务中创建txn记录,使用记录的正存在来表示成功。如果你长期保持这个记录,它基本上是一个交易历史。

    此级别的事务确定性会增加额外的写入操作并增加明显的延迟,因此您可能只想在确实需要准确性时使用它。