我正在做的是创建一个交易
1)实体A的计数器更新为+1
2)将新实体B写入数据存储区。
看起来像这样:
WrappedBoolean result = ofy().transact(new Work<WrappedBoolean>() {
@Override
public WrappedBoolean run() {
// Increment count of EntityA.numEntityBs by 1 and save it
entityA.numEntityBs = entityA.numEntityBs +1;
ofy().save().entity(entityA).now();
// Create a new EntityB and save it
EntityB entityB = new EntityB();
ofy().save().entity(entityB).now();
// Return that everything is ok
return new WrappedBoolean("True");
}
});
我正在做的是保持EntityB的entityA有多少。这两个操作需要在一个事务中进行,因此要么两次保存都要发生,要么都不发生。
但是,许多用户可能正在执行包含上述事务的api方法。我担心我可能会遇到太多人试图更新entityA的问题。这是因为如果多个事务尝试更新同一个实体,则第一个提交获胜但其他所有实体都失败。
这引出了两个问题:
1)如果对API方法进行了大量调用,那么我写了一个坏主意的事务并且注定不会导致写入?有没有更好的方法来实现我想要做的事情?
2)如果对不在事务中的实体进行了大量更新(例如更新实体具有的计数器),如果在进行大量更新时最终会遇到扩展问题,该怎么办?很短的时间?数据存储区如何处理这个问题?
对于长篇大论的问题,我很抱歉,但我希望有人可以通过上述问题了解这个系统对我的影响。感谢。
编辑:当我的意思是在很短的时间内对实体进行了大量更新时,请考虑像Instagram这样的内容,在那里你想要跟踪图片有多少“喜欢”。一些用户拥有数百万粉丝,当他们发布新图片时,他们可以得到10-50个像一秒钟的东西。
答案 0 :(得分:1)
数据存储区允许每个实体组大约写入1个/秒。可能不显而易见的是,独立实体(即没有父项且没有子项的实体)仍然属于一个实体组 - 它们自己的实体。因此,对同一独立实体的重复写入将受到相同的速率限制。
超过写入限制最终会导致写操作失败,例如TransactionFailedError(Concurrency exception.)
对在事务外部完成的同一实体的重复写入可以相互覆盖。事务可以帮助解决这个问题 - 冲突的写入会自动重试几次。从这个角度看你的方法看起来不错。但它只有在平均写入速率低于限制时才有效。
您可能想阅读Avoiding datastore contention。您需要shard your counter才能以超过1 /秒的速率计算事件。