我想要一些在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()
会给出非常一致的结果。然而,我在任何地方都没见过这种方法。这样做合理吗?有什么缺点我需要了解吗?在
我认为您还将不一致查询的问题与数据的安全更新混为一谈。在
与示例
UserGroupData.query(UserGroupData.users_in_group==user_id).get()
中的查询类似的查询将始终只返回一个实体,如果用户标识在组中。在如果它只是刚刚被添加,而索引不是最新的,那么您将不会得到一个记录,因此您不会更新该记录。在
任何与获取实体的方法无关的更新都应该在事务中执行,以确保更新的一致性。在
至于改进查询一致性的祖先,如果计划有多个UserGroupData实体,就不明显了。在这种情况下,为什么要执行get()。在
所以选项3,可能是你的最佳选择,只做关键字查询,然后在事务内部执行钥匙()并更新。请记住,跨组事务仅限于5个实体组。在
如果使用这种方法,如果查询所基于的索引已过期,则可能发生3种情况中的1种
然后,您的代码可以决定什么样的操作过程。在
查询某个特定用户所属且需要更新的所有UserGroupData实体的用例是什么?在
相关问题 更多 >
编程相关推荐