2013-08-19 55 views
0

我使用Python创建了Google App Engine应用程序。该应用程序处理大量用户名。Google App Engine高效数据存储读取/写入操作以保存配额

它有一个数据库到50K用户名。每个用户名都有一个唯一的哈希值。这也存储在数据存储中。

当任何应用程序用户提交任何用户名。应用程序首先检查用户名是否存在于数据库中。

如果它是一个新的用户名,应用程序将计算新名称的新散列并将名称和散列存储在DataStore中。

如果数据存储中已存在用户名,它将从数据存储中检索旧的散列。

示例代码:

class Names(db.Model): 
    name = db.StringProperty(required=True) 
    hash = db.StringProperty(required=True) 

username = "debasish" 
user_db = db.GqlQuery("SELECT * FROM Names WHERE name=:1", username) 
user = user_db.get() 
if user == None: 
    #doesn't exist in DB..so calculate new hash for that name and store it in DB 
    e = Names(name=username,hash="badasdbashdbhasbdasbdbjasbdjbasjdbasbdbasjdbjasbd") 
    e.put() 
else: 
    #retrieve the old hash. 
    self.response.out.write('{"name":"'+user.name+'","hash":"'+user.hash+'"}')    

我现在面临的问题是GAE的免费数据存储读取操作quota.Its超过太快,我的应用程序停止工作。

我也试着实现memcache,就像这样,在memcache中添加整个数据库。但这也是一个失败,结果更糟糕。

def get_fresh_all(self): 
    all_names = db.GqlQuery("SELECT * FROM Names") 
    memcache.add('full_db', all_names, 3600) 
    return all_names 

所以,大家可以请你建议,我做错了什么? 如何让数据存储读取操作更高效?

Thanks in Adv。

+0

您应该考虑使用“用户名”作为实体的关键字,那么您不需要执行查询。这比查询快得多(且操作更少)。然后你只需要'Names.get_by_id(name)' –

+0

这是你的应用程序的全部功能吗?如果是这样,由于您有许多用户,所以您的用户数量已经不足了。只需在2或3天内分割你的写作。 TimHoffman的建议将会使您的阅读操作减少至少一半。否则,您必须提供一些关于您正在执行的操作,以达到您的读取配额。如果你只有很多用户访问你的网站,那么缓存(即ndb)将有所帮助。 – dragonx

+0

请注意 - 来自ndb缓存的文档 - 查询不会在任何缓存中查找值。但是,如果高速缓存策略如此说明(但从不到Memcache),则查询结果将写回到上下文高速缓存中。所以ndb将不会为重复查询提供任何好处,只会得到() –

回答

0

您应该仅缓存username = hash而不是全部。加上内存缓存(这只适用于每个实例只缓存。应该帮助更多,只需在全局模块级别创建一个字典)。这可能会迅速增长,具体取决于您的独特点击率,但您可以添加逻辑来仅保存某些数字。这里是一个示例:

cache = {} 

def get_user_hash(username): 
    if username in cache: 
     return cache[username] 
    hash = memcache.get(username) 
    if not hash: 
     hash = # retrieve from db 
     if not hash: 
      # put to db & assign hash=new_hash 

     cache[username] = hash 
     memcache.set(username, hash) 
    return hash 
0

@费萨尔的方法应该运行良好,它会为查询添加两级缓存。

另一种选择是在会话中存储用户名和散列。每个会话只检查一次数据库,然后从会话变量中检索值。

3

,您可以:

  • 切换到NDB,其中的缓存是自动的
  • 查询键,而不是实体SELECT __key__ FROM ...
  • 降低相关指标(当然降低写入OPS,甚至阅读OPS)
  • 重写所有的实体如用户名和KEY_NAME使用的方法get_or_insert()
user = Names.get_or_insert("debasish", hash="badasdbashdbhasbd") 
+0

您绝对应该切换到NDB,并尽可能避免查询(通过键/ ID来获取实体) –

相关问题