سؤال

I am trying to understand how ndb uses memcache. From what I gathered so far a request to get() should check if the entity is in memcache already, if it is then retrieve it from memcache and therefore avoid hitting the datastore. If the entity is not in memcache the request is made to the datastore and memcache is updated.

Using Appstats I obtained the following numbers for the case when an entity is in the datastore but it is not yet in memcache:

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

My expectation for this scenario is:

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

Here is my code:

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()

Here is the screenshot from Appstat: Appstat screenshot

So why is there an extra Get and an extra Set request to memcache?

هل كانت مفيدة؟

المحلول

ndb needs to do multiple memcache sets and gets in order to avoid potential race conditions because there are no Datastore-memcache transactions. In order to do this correctly, ndb needs to lock memcache and ensure that only one ndb tasklet actually updates the memcache entry.

When you perform a get() for an entity not in memcache, the following happens:

  1. Check memcache for entity.
  2. The entity wasn't found, write a LOCK value to the memcache key for this entity.
  3. Do another immediate memcache get to get the cas token.
  4. Do a get from datastore.
  5. Put the entity in memcache with compare and swap.

The extra Set (step 2) is from locking the memcache entry associated with the entity while you get it from the datastore.

The extra Get (step 3) is to get the compare and swap token. This ensures that if the memcache entry was updated between steps 2 and 5, the tasklet will not overwrite the memcache entry.

If you're interested, I would recommend looking at the code that does this.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top