GAE中根实体的强一致性查询?

2024-10-03 04:35:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我想要一些在googleappengine中实现强一致读/写的最佳方法的建议。在

我的数据存储在这样的类中。在

class UserGroupData(ndb.Model):
  users_in_group = ndb.StringProperty(repeated=True)
  data = ndb.StringProperty(repeated=True)

我想为这个数据编写一个安全的更新方法。据我所知,我需要避免最终一致的读取,因为它们有丢失数据的风险。例如,以下代码不安全,因为它使用最终一致的常规查询:

^{pr2}$

如果查询返回的实体已过时,则数据将丢失。在

为了达到强烈的一致性,我似乎有几个不同的选择。我想知道哪个选项是最好的:

选项1:

使用get_by_id(),它总是强一致的。然而,这里似乎没有一个简单的方法来做到这一点。没有一种干净的方法直接从user_id派生UserGroupData的密钥,因为这种关系是多对一的。要求外部客户存储并发送UserGroupData的密钥似乎也有点脆弱和风险。在

选项2: 将我的实体放在祖先组中,然后执行祖先查询。比如:

def update_data(user_id, additional_data):
  entity = UserGroupData.query(UserGroupData.users_in_group==user_id,
                               ancestor=ancestor_for_all_ugd_entities()).get()
  entity.data.append(additional_data)
  entity.put()

我认为这应该行得通,但是将所有UserGroupData实体放入一个单一的祖先组似乎是一件极端的事情。这会导致写入被限制在~1/s。这似乎是错误的方法,因为每个UserGroupData实际上在逻辑上是独立的。 实际上,我想做的是对根实体执行强一致性查询。有什么办法吗?我注意到一个建议in another answer基本上是切分祖先群体。这是能做的最好的吗?在

选项3:

第三个选项是执行keys_only查询,然后是get_by_id(),如下所示:

def update_data(user_id, additional_data):
  entity_key = UserGroupData.query(UserGroupData.users_in_group==user_id,
                                   ).get(keys_only=True)
  entity = entity_key.get()
  entity.data.append(additional_data)
  entity.put()

据我所知,这个方法是安全的,不会丢失数据,因为我的键没有改变,get()会给出非常一致的结果。然而,我在任何地方都没见过这种方法。这样做合理吗?有什么缺点我需要了解吗?在


Tags: 数据方法in实体iddataget选项
1条回答
网友
1楼 · 发布于 2024-10-03 04:35:13

我认为您还将不一致查询的问题与数据的安全更新混为一谈。在

与示例UserGroupData.query(UserGroupData.users_in_group==user_id).get()中的查询类似的查询将始终只返回一个实体,如果用户标识在组中。在

如果它只是刚刚被添加,而索引不是最新的,那么您将不会得到一个记录,因此您不会更新该记录。在

任何与获取实体的方法无关的更新都应该在事务中执行,以确保更新的一致性。在

至于改进查询一致性的祖先,如果计划有多个UserGroupData实体,就不明显了。在这种情况下,为什么要执行get()。在

所以选项3,可能是你的最佳选择,只做关键字查询,然后在事务内部执行钥匙()并更新。请记住,跨组事务仅限于5个实体组。在

如果使用这种方法,如果查询所基于的索引已过期,则可能发生3种情况中的1种

  1. 找不到所需的记录,因为新添加的用户标识未反映在索引中。在
  2. 找到所需的记录,get()将一致地获取它
  3. 找到了所需的记录,但用户标识实际上已被删除,索引已过期。get()将一致地检索索引,并且userid不存在。在

然后,您的代码可以决定什么样的操作过程。在

查询某个特定用户所属且需要更新的所有UserGroupData实体的用例是什么?在

相关问题 更多 >