Google App Engine数据存储查询返回陈旧数据
我有一个基于GAE的项目,使用db
Datastore
。在我的项目中,我每15分钟运行一次作业,并更新Datastore
中的数据。然后我有一个端点查询Datastore
并显示结果。但是,我得到的结果是陈旧的,而不是更新的结果。看来GAE没有打到Datastore
并从缓存中返回数据,但我不确定。这里是我的代码:Google App Engine数据存储查询返回陈旧数据
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数据存储?我在这里错过了什么?
数据存储区最终只对查询一致。在数据复制过程中,确实存在一种可能性,那就是您打到“陈旧”的数据。
为了确保您在查询中强制保持一致性,您需要使用祖先查询或get by键。
了解更多关于这个here
例:祖先查询
(documentation)为了做到这一点,你显然需要改变你的结构位。我不知道什么可能是模型“竞赛”的祖先,但我们假设他们都属于“主祖先”实体。
当您创建实体,你需要有一个类似于:
query = Contests.all()
query.ancestor(mainAncestor)
contests = query.fetch(1)
这将迫使强:
newContest = Contest(parent=mainAncestor)
然后,当您检索,您在代码中添加此数据的一致性。您显然需要创建该“mainAncestor”,然后它会导致您需要确保解决的其他警告(例如,您只能每秒钟向实体组(在同一祖先下编组的实体)写入一次),例如)。
很好的答案,但要使它很棒我有两个建议:(一)你也可以直接链接到https://cloud.google.com/developers/articles/balancing-strong-and-eventual-consistency-with-google-云数据存储/(不需要通过那个以Java为核心的SO Q :-)来发送OP,而且(B)理想地提供了一个简单的Python例子,说明如何在OP的用例中人为地使用祖先查询...我upvoted无论如何,但建议你丰富答案!) – 2015-02-07 19:43:34
公平点。对于A)来说,这实际上是我打算使用的链接。我应该仔细检查。我会纠正这一点,并简单地添加B :)。感谢您的建议 – Patrice 2015-02-07 19:46:54
@Patrice @AlexMartelli非常感谢您的帮助!但即使在添加祖先查询并试图通过'key'获取数据之后,它也不起作用。我已经编辑了更多细节的问题。 – 2015-02-09 07:11:29
Patrice的回答是正确的 - 旧的crufty'db'并不会透明地为你缓存,你需要新的伟大的'ndb'(当然,通过使用自定义上下文来控制),所以遇到的问题'db'不能由于缓存,必须与最终一致性相关, – 2015-02-07 19:31:49
最终一致性需要1-2秒才能解决。如果您的数据超出了“陈旧”,那么您的代码中就有一个问题。 – 2015-02-07 19:35:34
@AndreiVolgin,第二个或通常更少是* typical *,但没有保证最坏情况延迟的上限。现代子系统(如ndb)的用户几乎从未观察到,因为memcache **具有强烈的一致性(虽然是volatile) - 但是对于旧的crufty db来说更加突出,反正“几乎没有”与“never”一样: - )... – 2015-02-07 19:47:31