客观化 - 许多人在短时间内与同一实体进行交易

时间:2016-07-05 03:51:54

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

我正在做的是创建一个交易

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个像一秒钟的东西。

1 个答案:

答案 0 :(得分:1)

数据存储区允许每个实体组大约写入1个/秒。可能不显而易见的是,独立实体(即没有父项且没有子项的实体)仍然属于一个实体组 - 它们自己的实体。因此,对同一独立实体的重复写入将受到相同的速率限制。

超过写入限制最终会导致写操作失败,例如TransactionFailedError(Concurrency exception.)

对在事务外部完成的同一实体的重复写入可以相互覆盖。事务可以帮助解决这个问题 - 冲突的写入会自动重试几次。从这个角度看你的方法看起来不错。但它只有在平均写入速率低于限制时才有效。

您可能想阅读Avoiding datastore contention。您需要shard your counter才能以超过1 /秒的速率计算事件。