是否为Google App Engine(Java)实体提供了父保证一致性?

时间:2015-08-25 14:28:47

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

我有一个Java风格的Google App Engine应用程序,我需要经历多个阅读周期,然后将数据写入数据存储区。每个周期取决于能够从最后写入中读取最新数据。

阅读Google文档,似乎保证此行为的方法是将创建的实体绑定到公共父级,即新实体(entity,parentKey)。

这里的问题是编写具有相同祖先(父)实体的实体是否确实保证了一致性?似乎父实体与子节点具有相同的问题 - 多个实例可能存在于不同的数据存储区中。对此的清晰度非常感谢。

2 个答案:

答案 0 :(得分:0)

使用相同的祖先(父)实体编写实体 DOES 确实保证了一致性。

如何吗

你想知道这是怎么回事:“看起来父实体会和孩子们有同样的问题 - 多个实例可能存在于不同的数据存储中。”

答案是,有一个非常复杂的算法(谷歌用于Megastore论文,PAXOS算法,如果你对技术细节感兴趣)在实体组上实现ACID交易,即使实体在不同的机

为什么要将ACID限制为实体组?

您可能想知道为什么他们不为整个数据存储区执行此操作。看起来他们想出了如何对分布的实体进行ACID事务,那么为什么不实现它而不管实体分组?

的答案是ACID事务是有代价的,成本是这样的:每秒最多只能写入一个实体组5次(实际上更像是每秒写入5次事务,因此可以在同一事务中批量写入以获得更好的写入吞吐量)。因此,如果他们为整个数据库执行此操作,那么对于他们所针对的互联网规模来说实际上是无用的。

写完背后阅读:

作为旁注,如果您在修改实体后(在同一事务中)读取实体,则必须小心。数据存储区事务的语义是这样的,即读取数据显示在事务的 start 处。这意味着它不会看到事务中发生的写入。

推荐阅读(好,观看)

如果您正在使用数据存储区,这几乎是需要观看的视频。它会为您解决很多这些问题:Google I/O 2011: More 9s Please: Under The Covers of the High Replication Datastore

答案 1 :(得分:-1)

  

似乎保证此行为的方法是将创建的实体绑定到公共父级,即新实体(entity,parentKey)。

正确,这使子实体属于同一个实体组。

  

似乎父实体与子节点具有相同的问题 - 多个实例可能存在于不同的数据存储区中。

这也是正确的。每个根实体(即没有父本身的实体)属于其自己的实体组。

我解决这个问题的方法是对数据库进行建模,使当前处理周期所需的所有数据共享同一个实体组,并在事务上读/写它,以便仍然能够在某种程度上维护并发性(类似于“在不同实例上处理不同用户”之类的内容,其中每个用户的所有数据都在同一个组中。)

如果你需要同时处理所有类型的实体,比如在快照中,我担心AppEngine的数据存储不是真正的最佳选择。您可以让所有实体成为硬编码root之类的孩子:

Key root = KeyFactory.createKey(kind, "root");
new Entity(entity, root);

它可以工作,但它带来了很多问题 - 主要的一点是它会减慢你的应用程序,因为你不能一次执行多次写入。您可以阅读更多相关信息here