何时在Google App Engine中使用某种类型的持久性?

时间:2009-07-28 11:53:14

标签: google-app-engine persistence

首先,我将解释这个问题。通过持久性,我的意思是存储数据超出单个请求的执行。它可能不是最好的问题标题,所以随时编辑它。

我看到它的方式,GAE中有三种类型的持久性,每种类型都与请求本身“更接近”:


数据存储区

这是所有数据最有可能的基础。它可能暂时进入更高层的持久性,但最终,这就是数据的真正含义。不幸的是,重复查询数据存储区很慢并且占用了大量资源。

在......时使用

  • 存储应无限期存储的数据。

避免在......时使用

  • 获取经常查询但很少更新的数据。

内存缓存

这是一个高度复杂的缓存引擎,它将数据存储在内存中,并确保所有用户都读取/写入同一缓存。与使用数据存储区相比,以键→值为基础获取/设置数据的速度要快得多。不幸的是,数据只能在内存中停留很长时间,并且无法保证只要你告诉它就会停留在内存中;如果其他地方需要内存,数据可能随时消失。

在......时使用

  • 您需要更频繁地获取数据,而不是更新数据。即使数据需要经常更新,也可以通过设置task queue将数据从内存缓存保存到数据存储区来使用(如果有少数错过的更新被认为是正常的)。

避免在......时使用

  • 数据需要经常更新,并且在获取时必须是最新的。

全局变量

这不是持久保存数据的官方方法,但它有效。但是,它是最不可靠的方法,并且由于它没有跨服务器的数据同步,持久化数据可能对不同的用户显示不同(但从我发现的,服务器很少为同一用户更改。)理论上,这应该是获取/设置值的开销最小的方法,并且可以使用它。

在......时使用

  • 地狱冻结了?我不知道......我对实际依赖这种方法的幕后情况知之甚少。洽谈!

避免在......时使用

  • 您依赖服务器上的数据相同。

缓存

如果数据是特定于用户的,则可以将其作为cookie存储在用户的浏览器中。但是有一些陷阱需要注意:

  • 安全性 - 用户可以插入cookie,恶意用户也可以这样做。为了确保内容不可读且不可更改,可以使用GAE上提供的PyCrypto库对cookie进行加密。
  • 性能 - 由于Cookie是通过每个请求(甚至是图像)发送的,因此可以增加正在使用的带宽,并减慢请求速度。一种解决方案是将另一个域用于静态内容,因此浏览器不会发送该内容的cookie。

什么时候应该使用不同类型的持久性?如何将它们结合起来以减少/平衡所花费的资源量?

4 个答案:

答案 0 :(得分:1)

<强>数据存储

使用数据存储区保存任何长期生活信息。应该使用数据存储区,就像使用普通数据库来保存将在您的站点/应用程序中使用的数据一样。

<强> MEMCACHE

使用此选项可以比尝试访问数据存储区更快地访问数据。 MemCache可以非常快速地返回数据,并且可以用于需要跨越用户多次呼叫的任何数据。它通常是最初在数据存储区中的数据,然后移动到memcache。

def get_data():
  data = memcache.get("key")
  if data is not None:
    return data
  else:
    data = self.query_for_data() #get data from the datastore
    memcache.add("key", data, 60)
    return data

当项目过期时,内存缓存将自动刷新。您可以在上面显示的添加的最后一个参数中设置它。

全局变量 我根本不会使用它们,因为它们不能跨越实例。在GAE中,请求创建一个新实例,在python中它就是这样。如果你想使用全局变量,我会存储memcache中所需的数据。

答案 1 :(得分:1)

您的帖子是对3个主要选项的一个很好的总结。你们大多已经回答了这个问题。但是,如果您正在构建应用程序并强调是否应该记忆某些内容,请尝试以下操作:

  1. 使用数据存储区编写应用程序,以查找需要超过一个请求的所有内容。
  2. 一旦您的应用程序(或某些可用的子集)正常工作,请运行一些功能测试或模拟以查看慢点(或高配额使用率)的位置。
  3. 查找最慢或效率最低的请求路径,并找出如何更快地执行此操作(通过使用内存缓存或更改数据结构,以便您可以执行获取而不是查询,或者可能将某些内容存储在全局实例变量中*)
  4. 转到2直到你满意为止。
  5. * 可能对“全局”变量有用的东西将是创建/获取相对昂贵的东西,您的大部分请求将使用,并且不需要在请求/用户之间保持一致。

答案 2 :(得分:1)

我使用全局变量来加速json转换。在我将数据结构转换为json之前,我将其哈希并检查json是否已经可用。对于我的应用程序,这提供了相当快的速度,因为纯python实现非常慢。

答案 3 :(得分:1)

全局变量

为了补充AutomatedTester的答案,还回答了他关于如何在没有 内存缓存或数据存储的GET 之间共享信息的进一步问题,下面简单介绍如何使用全局变量:

if 'i' not in globals():
    i = 0

def main():
    global i
    i += 1
    print 'Status: 200'
    print 'Content-type: text/plain\n'
    print i

if __name__ == '__main__':
    main()

多次调用这个脚本会给你1,2,3 ......当然如前面提到的Blixt你不应该过分依赖这个技巧('我有时可以切换回零)但它可以是用于将用户特定信息存储在字典中,例如会话数据。