3

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

预期行为:实体应该出现在查询中,因为我将 NDB 用于我的数据存储区,它会自动缓存事物。

问题重现步骤

  1. 在适用于 Mac 的 GoogleAppEngineLauncher 1.8.3 中创建一个默认项目(我的操作系统版本是 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。

4

4 回答 4

3

我设法得到了我的预期行为,我更新的代码如下。我从具有我期望的行为的“留言簿”示例代码中得到了一个提示,并设置了一个父键。我还深入研究了 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)

感谢阅读和参与。

于 2013-09-02T21:46:03.453 回答
2

这就是最终一致性的行为。我不确定您要做什么,也许您可​​以更改数据建模,因此 fetch 始终保持高度一致。

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

于 2013-09-02T03:42:28.473 回答
1

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

具体来说,文档说-

查询不会在任何缓存中查找值。但是,如果缓存策略如此,查询结果将被写回上下文缓存(但永远不会写回 Memcache)。

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

另请参阅有关相同 ndb 和 memcache 的 SO question,自动 NDB 缓存如何工作?

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

于 2013-09-01T23:21:43.497 回答
1

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

对于这一行:

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

它应该是:

entities = SmallModel.ancestor(parent_key())
于 2017-06-14T18:46:20.833 回答