【问题标题】:Google App Engine Datastore query returning stale dataGoogle App Engine Datastore 查询返回陈旧数据
【发布时间】:2015-04-07 19:17:58
【问题描述】:

我有一个基于 GAE 的项目,使用 db Datastore。在我的项目中,我每 15 分钟运行一次作业,并更新 Datastore 中的数据。然后我有一个查询Datastore 并显示结果的端点。但是,我得到的结果是陈旧的,而不是更新的结果。似乎 GAE 没有命中 Datastore 并从缓存中返回数据,但我不确定。这是我的代码:

class MainHandler(webapp2.RequestHandler):

    def get(self):
        query = Contests.all()
        contests_data = query.fetch(1) # fetch the data from datastore
        self.response.write(contests_data[0].data)

class DataBaseHandler(webapp2.RequestHandler):

    # the job that runs every 15 minutes
    def get(self):
        contests_data = get_all_contests() # get the new data
        query = Contests.all()
        contests = query.fetch(1)
        contests[1].data = contests_data # update the data
        db.put(contests[0])
        self.response.write(json.dumps({"message":"updated"}))

这是我的模型:

class Contests(db.Model):
    """Models Contests"""
    data = db.TextProperty(default="{}")
    created = db.DateTimeProperty(auto_now_add=True)
    modified = db.DateTimeProperty(auto_now=True)

我尝试使用memcache.flush_all() 清除缓存,但即使这样也不能解决问题。为什么 GAE 不返回更新的数据?我该如何解决这个问题?

编辑:我将查询更改为祖先查询,但数据仍然过时(而且已经有好几天了)。

main.py

class MainHandler(webapp2.RequestHandler):

        def get(self):
            contest_list = ContestList.get_or_insert('contest_list', name='ContestList')
            query = Contests.all()
            query.ancestor(contest_list) 
            contests = query.fetch(1)
            self.response.write(contests[0].data)

    class DataBaseHandler(webapp2.RequestHandler):

        def get(self):
            contests_data = get_all_contests()
            contest_list = ContestList.get_or_insert('contest_list', name='ContestList')
            query = Contests.all()
            query.ancestor(contest_list)
            contests = query.fetch(1)
            contests[0].data = contests_data
            contests[0].put()
            self.response.write(json.dumps({"message":"updated"}))

models.py:

class ContestList(db.Model):
    name = db.StringProperty()

class Contests(db.Model):
    """Models Contests"""
    data = db.TextProperty(default="{}")
    created = db.DateTimeProperty(auto_now_add=True)
    modified = db.DateTimeProperty(auto_now=True)

我什至尝试使用key获取数据:

class MainHandler(webapp2.RequestHandler):

    def get(self):
        q = ndb.Key('Contests', 'contest_data').get()
        if q:
            self.response.write(q.data)
        else:
            self.response.write("error")

class DataBaseHandler(webapp2.RequestHandler):

    def get(self):
        Contests(key=ndb.Key('Contests', "contest_data"), data=get_all_contests()).put()
        self.response.write(json.dumps({"message":"updated"})) 

GAE 没有击中数据存储区的是什么?我在这里错过了什么?

【问题讨论】:

  • Patrice 的回答是正确的——而且老粗鲁的 db 无论如何都不会透明地为你做缓存,你需要闪亮的新的伟大的 ndb (当然可以通过使用自定义上下文来控制) ,因此db 出现的问题不可能是由于缓存造成的,必须与最终一致性有关,
  • 最终一致性需要 1-2 秒才能自行解决。如果您的数据“过时”超出此范围,则说明您的代码中某处存在问题。
  • @AndreiVolgin,一秒甚至更少是典型的,但对于最坏情况的延迟没有保证上限。现代子系统(例如 ndb)的用户几乎没有观察到这一点,因为 memcache is 高度一致(尽管易变) - 但它在旧的粗鲁 db 中更为突出,而且无论如何“几乎从来没有" 与 "never" 完全一样:-)...
  • 您的 cmets 令人困惑:NDB 不缓存查询,因此在这种情况下会产生零差异。
  • @Greg 实际上 NDB 的全部意义在于将您的结果缓存到内存缓存中并在检查数据存储之前去那里...

标签: python google-app-engine caching model google-cloud-datastore


【解决方案1】:

数据存储区仅对查询具有最终一致性。在复制数据期间,确实有可能遇到“陈旧”数据。

为确保在查询中强制实现强一致性,您需要使用祖先查询或按键获取。

阅读更多关于这个here

例如:祖先查询

(documentation) 要做到这一点,你显然需要稍微改变你的结构。我不知道模型“竞赛”的祖先可能是什么,但假设它们都属于“mainAncestor”实体。

当您创建实体时,您需要有类似的东西:

newContest = Contest(parent=mainAncestor)

然后,当您检索时,将其添加到您的代码中:

query = Contests.all()
query.ancestor(mainAncestor) 
contests = query.fetch(1)

这将强制您的数据保持高度一致性。您显然需要创建该“mainAncestor”,然后它会导致您需要确保解决的其他警告(例如,您只能每秒写入一次实体组(分组在同一祖先下的实体) )。

【讨论】:

  • 很好的答案,但为了让它变得更好,我有 2 条建议:(A) 您也可以直接链接到 cloud.google.com/developers/articles/…(无需通过以 Java 为重点的 SO Q 发送 OP :-) 和(B) 理想情况下,还提供一个简单的 Python 示例,说明如何在 OP 的用例中人为地使用祖先查询...无论如何我都赞成,但建议您丰富答案!-)
  • 公平点。对于 A),这实际上是我打算使用的链接。我应该仔细检查一下。我会更正它并很快添加 B :)。感谢您的建议
  • @Patrice @AlexMartelli 非常感谢您的帮助!但即使添加了祖先查询并尝试通过key 获取数据,它也不起作用。我已编辑问题以获取更多详细信息。
猜你喜欢
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多