【问题标题】:App Engine High Replication DatastoreApp Engine 高复制数据存储
【发布时间】:2011-09-04 15:18:58
【问题描述】:

我是一个 App Engine 新手,我想确认我对高复制数据存储的理解。

文档说实体组是一个“一致性单元”,所有数据最终都是一致的。同样,它还说“跨实体组的查询可能过时”。

有人可以提供一些查询可能“过时”的示例吗?是不是说我可以在没有任何父级的情况下保存一个实体(即它自己的组),然后很快查询它却找不到它?这是否也意味着如果我希望数据始终 100% 保持最新,我需要将它们全部保存在同一个实体组中?

常见的解决方法是使用 memcache 缓存实体的时间长于数据在所有数据中心内保持一致所需的平均时间吗?大概的延迟是多少?

谢谢

【问题讨论】:

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


    【解决方案1】:

    是不是说我可以节省 一个没有任何父母的实体(即它是 自己的组),然后非常查询它 很快就找不到了?

    正确。从技术上讲,常规主从数据存储也是如此,因为索引是异步更新的,但实际上发生这种情况的时间窗口非常小,您永远看不到它。

    如果“查询”是指“按键获取”,那么在任一实现中都将始终返回高度一致的结果。

    是否也暗示如果我想要数据 要始终保持 100% 的最新状态,我需要 将它们全部保存在同一个实体中 组?

    您需要先定义“100% 最新”的含义,然后才能回答这个问题。

    这是常见的解决方法 使用 memcache 缓存实体 比平均时间长的时间 数据变成所需的时间 在所有数据中心保持一致?

    没有。 Memcache 严格用于提高访问时间;你不应该在缓存驱逐会导致麻烦的任何情况下使用它。

    如果您需要确保看到的是最新版本,您始终可以使用高度一致的获取。但是,如果没有具体示例说明您正在尝试做什么,就很难提供建议。

    【讨论】:

    • 很抱歉我没有具体的例子。我正在尝试学习该系统,以便我可以开始我的项目。我只是希望能够将数据存储在数据存储中,并在需要时检索最新版本。我只是想弄清楚什么时候不是这种情况,以及如何保证当我查询结果时我会得到最新鲜的结果。通过“查询”,我的意思是按属性进行查询,就像在 SQL 中那样,而不是按键。我只是想了解他们所说的祖先组是什么意思是“一致性单位”以及什么可以是“不一致”。
    • Nick,在本文档的使用说明部分:code.google.com/intl/en/appengine/docs/python/datastore/hr/… 说“您可以将最近的帖子放入内存缓存中并过期,然后显示来自内存缓存的最近帖子和从数据存储。”。
    • @user439383 (您是否考虑过设置一个更有用的用户名?)就我个人而言,我不会担心这个,直到/除非您有特殊情况需要关注。最终一致的语义适用于大多数情况,并且您会知道何时需要强一致性。
    • 很好的答案,尼克。我只是想确认你所说的。 '如果通过“查询”你的意思是“通过键获取”,那么这将始终在任一实现中返回高度一致的结果。'。所以,如果我这样做:MyNDBModal.get_by_id(theID),我会总是找到它,即使它是最近写的?
    【解决方案2】:

    强制性博客示例设置; AuthorsPosts

    class Author(db.Model):
        name = db.StringProperty()
    
    class Post(db.Model):
        author = db.ReferenceProperty()
        article = db.TextProperty()
    
    bob = Author(name='bob')
    bob.put()
    

    首先要记住的是,单个实体组(包括单个实体)上的常规 get/put/delete 将按预期工作:

    post1 = Post(article='first article', author=bob)
    post1.put()
    
    fetched_post = Post.get(post1.key())
    # fetched_post is latest post1
    

    如果您开始跨多个实体组进行查询,您只会注意到不稳定。除非您指定了 parent 属性,否则您的所有实体都位于单独的实体组中。因此,如果在bob 创建帖子之后,他可以看到自己的帖子很重要,那么我们应该注意以下几点:

    fetched_posts = Post.all().filter('author =', bob).fetch(x)
    # fetched_posts _might_ contain latest post1
    

    fetched_posts 可能包含来自bob 的最新post1,但可能不会。这是因为所有Posts 不在同一个实体组中。在 HR 中进行这样的查询时,您应该认为 “为我获取鲍勃的最新帖子”

    由于在我们的应用程序中作者可以在创建后立即在列表中看到他的帖子很重要,我们将使用parent 属性将它们绑定在一起,并使用ancestor 查询仅获取帖子来自该组:

    post2 = Post(parent=person, article='second article', author=bob)
    post2.put()
    
    bobs_posts = Post.all().ancestor(bob.key()).filter('author =', bob).fetch(x)
    

    现在我们知道post2 将出现在我们的bobs_posts 结果中。

    如果我们查询的目的是获取 “可能是所有最新帖子 + 绝对是 bob 的最新帖子”,我们需要进行另一个查询。

    other_posts = Post.all().fetch(x)
    

    然后将结果other_postsbobs_posts合并在一起,得到想要的结果。

    【讨论】:

    • 这实际上是一个很好的解释。我唯一不明白的是您的示例中的person 是什么?类还是实例?
    【解决方案3】:

    刚刚将我的应用程序从主/从数据存储迁移到高复制数据存储后,我不得不说,在实践中,最终一致性对于大多数应用程序来说都不是问题。

    考虑经典留言簿示例,您在其中put() 一个新留言簿帖子实体,然后立即查询留言簿中的所有帖子。使用 High Replication 数据存储,您将在几秒钟后看到新帖子出现在查询结果中(在 Google I/O 上,Google 工程师表示延迟大约为 2-5 秒)。

    现在,在实践中,您的留言簿应用可能正在对新留言簿帖子条目进行 AJAX 帖子。提交新帖子后无需重新获取所有帖子。一旦 AJAX 请求成功,webapp 可以简单地将新条目插入 UI。到用户离开网页并返回,甚至点击浏览器刷新按钮时,已经过了几秒钟,很可能会通过拉入所有留言簿帖子的查询返回新帖子。

    最后,请注意,最终一致性性能仅适用于查询。如果您put() 一个实体并立即调用db.get() 将其取回,则结果是强一致的,即您将获得该实体的最新快照。

    【讨论】:

      猜你喜欢
      • 2011-11-10
      • 2012-05-01
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      相关资源
      最近更新 更多