我仍然对交易感到困惑,无论是使用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();
}
});
重要的一点是,我希望系统不断尝试无限制。当然,我希望客户端调用返回,而所有这些都是异步发生的。谢谢你的帮助
答案 0 :(得分:1)
如果存在并发冲突,Objectify版本将重试。您可以修改DatastoreService版本以循环ConcurrentModificationException,您将获得相同的逻辑。
然而,这并不能让你得到一个非常准确的计数器(尽管它通常足够接近大多数用途)。但是,您不希望像这样运行银行交易。
问题(存在于所有分布式事务处理系统中)是在事务期间出现问题,例如,抛出DatastoreException。这使您的计数器处于不确定状态 - 提交是否成功?你不知道。
如果你想要准确(并且你确实说非常准确),你需要执行一些变化:
并且您需要某种查询来清除完全失败的事务的剩余txn记录。
这种变化是在事务之前创建id,并在事务中创建txn记录,使用记录的正存在来表示成功。如果你长期保持这个记录,它基本上是一个交易历史。
此级别的事务确定性会增加额外的写入操作并增加明显的延迟,因此您可能只想在确实需要准确性时使用它。