google-app-engine - 根实体中的 GAE 事务

标签 google-app-engine transactions google-cloud-datastore

我是 GAE 新手,对使用 DataStore 进行事务有一些疑问。

例如,我有一个用户实体,该实体是当用户在 Facebook 上添加我的应用程序时创建的。我通过 Facebook API 获得了一些属性,但我想为用户添加用户名,并且该用户名必须是唯一的。所以在事务范围内我调用这个方法:

def ExistsUsernameToDiferentUser(self, user, username):
    query = User.all()
    query.filter("username", username)
    query.filter("idFacebook != ", user.idFacebook)
    userReturned = query.get()
    return True if userReturned else False

但是 GAE 给了我这个错误:

BadRequestError: queries inside transactions must have ancestors

好的,我明白了,但是用户没有任何祖先,它是根实体。我必须做什么?

最佳答案

我明白你现在想做什么。

通过强制使用祖先,数据存储会强制您锁定数据存储的一部分(给定祖先下的所有内容),以便您可以保证该部分的一致性。然而,要做你想做的事,你本质上需要锁定所有 User 实体来查询某个 User 实体是否存在,然后创建一个新的 User 实体,然后解锁它们。

你可以这样做,只需创建一个实体,它可以是一个空实体,但确保它有一个唯一的键(如“用户祖先”),保存它,并使其成为每个用户实体的祖先。 这可能是一个坏主意,因为这会限制您在用户实体上的性能,特别是在写入方面。每次创建新用户时,所有用户实体都将被阻止更新。

我试图说明在 HRD 世界中您需要如何以不同的方式思考交易。您可以自行构建数据(使用祖先),以便为您的特定应用程序获得良好的性能特征。事实上,您可能不同意我的观点,并说用户实体更新的频率非常低,因此可以将它们全部锁定。

出于说明目的,另一种短视的可能性是根据用户名创建多个祖先。即,字母表中的每个字母对应一个。然后当你需要创建一个新的User时,你可以根据相应的祖先进行搜索。虽然这比拥有单一祖先有所改进(好 26 倍),但它仍然会预先限制您 future 的表现。如果您现在知道最终将拥有的用户总数,这可能没问题,但我怀疑您需要数亿用户。

最好的方法是返回其他建议并将用户名作为 key 。这为您提供了最佳的可扩展性,因为通过按键获取/设置用户实体可以是事务性的,并且不会锁定其他实体,从而限制您的可扩展性。

您需要找到一种方法来解决这个问题。例如,您在用户名之前获得的任何信息都可以存储在另一个实体中,该实体具有与稍后创建的用户相关的字段。或者,您可以在通过 key 创建用户实体后将该数据复制到用户实体中,然后删除原始实体。

关于google-app-engine - 根实体中的 GAE 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13662348/

相关文章:

python - GAE cron 重试参数

eclipse - Aptana Studio 3 + App Engine Python + 无法解析内存缓存的某些方法

java - 找出缺陷!使用任务队列可靠地执行长任务

google-app-engine - 如何从数据存储中获取 ID 以更新实体?

java - 如何更改有序+持久集合中的顺序?

google-app-engine - Google AppEngine 数据存储的 GUI

google-app-engine - 在 Django 模板中使用 webapp2.uri_for

python - 在 App Engine 应用程序初始化时执行代码

sql-server - 如何从 SQL Server 事务中刷新全文索引

c# - 提交后读取的 ServiceStack Ormlite 事务有时会返回 null