ndb对memcache的意外额外调用

时间:2014-03-27 20:17:04

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

我试图了解ndb如何使用memcache。从我到目前为止收集到的请求get()应该检查实体是否已经在memcache中,如果它是从memcache检索它,因此避免命中数据存储区。如果实体不在memcache中,则向数据存储区发出请求并更新内存缓存。

使用Appstats我获得了以下数字,表示当一个实体在数据存储区中但它还没有在memcache中时:

memcache.Get        2
memcache.Set        2
datastore_v3.Get    1

我对这种情况的期望是:

memcache.Get        1
memcache.Set        1
datastore_v3.Get    1

这是我的代码:

import webapp2
from google.appengine.ext import ndb 
from models import User

class IndexPage(webapp2.RequestHandler):
  def get(self):
    user_key = ndb.Key(User, 'user123')                                                                                                                                        
    u = user_key.get()

以下是Appstat的截图: Appstat screenshot

那么为什么对memcache有额外的Get和额外的Set请求?

1 个答案:

答案 0 :(得分:4)

ndb需要执行多个memcache集合,以避免潜在的竞争条件,因为没有Datastore-memcache事务。为了正确执行此操作,ndb需要锁定memcache并确保只有一个ndb tasklet实际更新了memcache条目。

当您为不在memcache中的实体执行get()时,会发生以下情况:

  1. 检查实体的memcache。
  2. 找不到实体,将LOCK值写入此实体的memcache密钥。
  3. 另一个即时memcache获取cas令牌。
  4. 从数据存储区获取。
  5. 将实体放在memcache中,并使用compare和swap。
  6. 额外Set(步骤2)来自锁定与实体关联的memcache条目,同时从数据存储区获取该文件。

    额外Get(步骤3)是获取比较和交换令牌。这确保了如果在步骤2和5之间更新了memcache条目,则tasklet将不会覆盖memcache条目。

    如果您有兴趣,我建议您查看code that does this

相关问题