【问题标题】:How we can ignore NDB cached query result?我们如何忽略 NDB 缓存的查询结果?
【发布时间】:2019-02-26 04:43:45
【问题描述】:

我有一个名为 SignupTokens 的模型,当用户从我们的聊天机器人确认他们时,我们使用 isUsed = True 更新实体,更新实体后,如果我们使用 isUsed = False 查询特定同一电子邮件的未使用令牌,那么一段时间结果是甚至已经用 True 更新了 isUsed 标志。每当我们遇到这个问题时,我们都会仔细检查数据存储实体是否单一。

SignupTokens.gql("where isUsed = :1 and email = :2",False,email).get()

我们已经尝试过使用_cache = False like

SignupTokens.gql("where isUsed = :1 and email = :2",False,email).get(use_cache=False)

请让我知道任何人对此有任何想法。

【问题讨论】:

    标签: python google-app-engine google-cloud-datastore gql


    【解决方案1】:

    这很可能不是 ndb 缓存问题,这是由于 eventual consistency 而导致的预期数据存储行为:从实体的 isUsed 属性设置为 True 到与您的索引对应的索引需要一些时间查询会相应更新。

    在更新索引之前,查询结果不会反映更改

    【讨论】:

    • 好的,除了 time.sleep 在代码中还有什么方法可以确认数据存储和索引是否已成功更新?
    • 我不知道确定索引是否/何时更新的方法。您可以将查询设为keys_only,然后通过键查找(始终保持一致)从查询结果中检索实体的实际内容,并检查isUsed 实际值。
    • 你的意思是key = SignupTokens.gql(..).get(keys_only=True)ndb.Key(key).get()
    • 差不多。该查询为您提供键列表,而不是键。然后为每个键执行key.get(),或者更有效的是ndb.get_multi(keys)(一次最多500个键)。
    • 我试过 keys = self.query(ndb.AND(self.isUsed == False, self.email == email)).fetch(keys_only=True)obj = keys[0].get() 仍然返回某个较旧的结果。
    【解决方案2】:

    正如@Dan 所建议的,这很可能不是ndb 缓存问题。这是您在连续读写同一个实体组时引起的问题。这是一种数据存储行为,基本上是由 datastore contentioneventual consistency 引起的。

    有一些方法可以避免这种情况。

    • 使用key 进行查询。每当您尝试通过其键读取对象时,它都是strongly consistent。所以,在你的情况下,我建议存储你正在更新的对象的密钥,如果可能的话,然后读取它并执行你想要的操作。

    • 另一种方法是使用 NDB 异步操作。在此处查看相关documentation

    • 您可以尝试提供可以帮助您的延迟,但应以足以更新对象的方式提供延迟。

    希望这能回答你的问题!!!

    【讨论】:

    • 即使是单次写入也可能发生,没有任何争用。在 Web 应用程序中经常看到在 GET 处理程序中使用查询的页面,修改 POST 处理程序中这些查询中使用的属性,然后重定向到相同的 URL - 下一个 GET 请求通常无法看到上一个所做的更改POST 请求。
    • 确实是@DanCornilescu。它在多个请求中也经常发生。
    猜你喜欢
    • 1970-01-01
    • 2017-12-05
    • 2011-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    • 2018-04-13
    • 1970-01-01
    相关资源
    最近更新 更多