应用程序引擎开发人员服务器数据存储更新速度不够快



问题:数据存储更新太慢——提交创建实体的表单后,需要在显示数据存储中实体的结果页面上点击reload。

预期行为:实体应该出现在它的查询中,因为我正在为自动缓存内容的数据存储使用NDB。

问题修复步骤

  1. 在GoogleAppEngineLauncher1.8.3 for Mac(我的操作系统版本是10.8.4)中创建一个默认项目,并将下面的代码粘贴到"main.py"中
  2. 运行项目并访问根URL
  3. 在表单中输入一个数字,然后单击提交
  4. 您将看到文本"这是实体列表:…结束列表。"
  5. 点击浏览器上的"重新加载"
  6. 现在,您将看到文本"这是实体列表:[您输入的编号]…结束列表。"

预期行为的解释

由于NDB自动使用memcache,因此不应执行步骤4和5。在表单上单击"提交"后,您输入的号码将显示出来。我在常规的appengine DB中也观察到了这种行为,我知道使用memcache可以绕过它。

以下是一些代码,您可以将其放入由复制此问题的AppEngineLauncher创建的默认main.py中:

import webapp2
from google.appengine.ext import ndb
class SmallModel(ndb.Model):
    n = ndb.IntegerProperty(required=True)
    stamp = ndb.DateTimeProperty(auto_now_add=True)
class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write('Hello world. Simple form. <form method="post"><input name="n" type="number"><input type="submit"></form>')
    def post(self):
        entity = SmallModel(n=int(self.request.get('n')))
        entity.put()
        self.redirect('/list')
class List(webapp2.RequestHandler):
    def get(self):
        self.response.out.write("here's a list of entities:")
        entities = SmallModel.query()
        for entity in entities.iter():
            self.response.out.write(" %s " % entity.n)
        self.response.out.write("...end list.")
app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/list',List)
], debug=True)

有什么帮助/建议吗?提前谢谢!我已经能够在我测试的两个浏览器中重新解决这个问题——Chrome和Safari。

我设法得到了预期的行为,更新后的代码如下。我从"留言簿"示例代码中得到了一个提示,该代码具有我所期望的行为,并设置了一个父键。我还深入研究了NDB文档。设置父密钥可以实现我所期望的一致性,但将写入限制为每秒一次(我假设这意味着对于给定父密钥的所有子项,而不是给定模型的所有实体)。

以下是我为消除步骤4和5所做的更改。我只是在新实体上设置了一个父关键字,并使用这个父关键字进行祖先查询。(当然,这是用于说明一点的超最小代码,我对创建数字列表的模型没有真正的兴趣。)

import webapp2
from google.appengine.ext import ndb
def parent_key():
    return ndb.Key('My','Entities')
class SmallModel(ndb.Model):
    n = ndb.IntegerProperty(required=True)
    stamp = ndb.DateTimeProperty(auto_now_add=True)
class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write('Hello world. Simple form. <form method="post"><input name="n" type="number"><input type="submit"></form>')
    def post(self):
        entity = SmallModel(parent=parent_key(),n=int(self.request.get('n')))
        entity.put()
        self.redirect('/list')
class List(webapp2.RequestHandler):
    def get(self):
        self.response.out.write("here's a list:")
        entities = SmallModel.query(ancestor=parent_key())
        for entity in entities.iter():
            self.response.out.write(" %s " % entity.n)
        self.response.out.write("...end list.")
app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/list',List)
], debug=True)

感谢您的阅读和参与。

这是最终一致性的行为。我真的不确定你想做什么,也许你可以改变你的数据建模,这样获取总是非常一致的。

在您的数字列表示例中,您可以将它们存储在一个实体的ListProperty中,这样您就可以始终以强一致的方式获取它

ndb非常明确,它不在memcache中查找查询结果。只有get()从memcache中获取实体。

具体来说,文件说-

查询不会在任何缓存中查找值。但是,查询结果如果缓存策略这么说,则会写回上下文中的缓存(但决不发送到Memcache)。

https://developers.google.com/appengine/docs/python/ndb/cache无正文缓存部分。

另请参阅关于相同ndb和memcache的SO问题,自动ndb缓存是如何工作的?

您可能会在生产中发现同样的问题。这是由于现在开发环境中正在模拟的最终一致性。您需要使用get来确保一致性,或者处理查询结果的潜在延迟。

我遇到了类似的问题。感谢您的解决方案。顺便说一句,我认为GAE文档已经从您的原始解决方案更改了。

对于这条线路:

entities = SmallModel.query(ancestor=parent_key())

应该是:

entities = SmallModel.ancestor(parent_key())

最新更新