GAE HDR:按键的实体检索最终是否在XG事务中保持一致?

fnf*_*fnf 10 java google-app-engine transactions eventual-consistency google-cloud-datastore

考虑"使用事务"中的第二个示例("使用命名密钥更新实体,或者如果它尚不存在则创建它"):

https://developers.google.com/appengine/docs/java/datastore/transactions

现在考虑这种情况.多人游戏只允许任意两个玩家之间的单一匹配.为了确保这一点,使用每个玩家的键创建一个键.此键用作UniqueMatch实体的键.

因此,为了创建匹配,将创建XG事务.在此交易中:

  1. 我们检查是否已经存在具有该密钥的UniqueMatch实体.如果使用该键的datastore.get()调用没有抛出EntityNotFoundException,那么我们知道这两个玩家之间的匹配已经存在,所以我们回滚()并向玩家显示错误消息.

  2. 我们将()所有需要放入的实体放入以创建匹配项.这包括UniqueMatch实体以及其他一些实体.

  3. 然后提交事务.

这似乎工作正常.但是,我注意到我可以在短时间内在任意两个玩家之间创建两场比赛.在一小段时间内(实际上其中一个测试中最多10-20秒),我对datastore.get(key)的调用抛出了EntityNotFoundException,即使该键已经被put().

这似乎是最终的一致性.但是,关键的实体回顾不是保证强烈一致吗?此保证是否受到在XG交易中完成的事实的影响?

提前致谢,

Rob*_*tis 1

我认为您看到的问题可能是因为数据存储区获取(通过键或查询)只能看到事务开始时数据存储区的状态。

来自文档(在隔离和一致性下):

在事务中,所有读取都反映事务启动时数据存储区的当前一致状态。这不包括事务内先前的放置和删除。事务内的查询和获取保证会看到截至事务开始时数据存储区的单个一致快照。

此外,在事务之外,您只会看到已提交的 put ( docs ):

通过查询或获取从数据存储中检索的实体将只能看到已提交的数据。

一个可能的解决方案:

在事务外部创建 UniqueMatch 实体(appengine 不允许您放置具有相同键的实体,因此如果具有相同键的实体已存在,它将引发异常)。然后,您可以创建/放置在事务内创建匹配所需的其他实体(如果需要)。

最后,确保在为 UniqueMatch 创建密钥时,它们的密钥始终以相同的顺序与玩家一起创建,因为key(playerA,playerB)!=key(playerB,playerA)