Skip to content
Navraj Chohan edited this page Feb 20, 2015 · 1 revision

The Memcache API is the simplest in the set of GAE APIs. It provides a key/value transient store, meaning what you place in may not be there when you look it up later. The cache is a set size, so the old objects which have not been fetched in some time or infrequently are kicked out and replaced with newer items. Some higher level libraries and APIs build on top of the Memcache API. These include NDB (Python) and Objectify (Java) which use memcache to optimize data fetches. This blog talks about its implementation in AppScale.

The API The API provided by GAE is nearly identical to the memcached API. Porting from one to another is trivial. The basic calls are set, get, delete, increment, and decrement. There are also functions which let you do gets, sets, and deletes in batches of key/value pairs. The high level reference to the API is here: https://cloud.google.com/appengine/docs/python/memcache/clientclass

Implementation The Application Servers take these calls and convert them to protocol buffer requests of the following types: MemcacheGetRequest MemcacheSetRequest MemcacheDeleteRequest MemcacheIncrementRequest MemcacheBatchIncrementRequest MemcacheFlushRequest MemcacheStatsRequest

Each of which contains specific parameters mapped over from the high level API. For example, the MemcacheSetRequest will specify the write policy of either set, add, replace, or check and set. Each Application Server (Python, Java, GO, PHP) implements memcache using the memcached API. The AppScale Controller lets the Application Servers know which nodes are currently hosting memcached daemons. This list must be the same on all nodes using memcache, otherwise hashing results are inconsistent from machine to machine.

The memcache objects are all stored as pickled objects or as protocol buffers to preserve the typing. This works fine, except for where we implement an atomic counter since the memcache system does not inherently know what the types we are storing inside the protocol buffer are or how to increment the value stored within it. For this we use memcache’s CAS (Check and Set). When an increment operation is requested, the original key is fetched along with its CAS identifier. Then a check and set operation is used to make sure the key has not been updated since, thus providing an atomic update.

Our Test Compatibility Key from Google shows that we have full fidelity with Google App Engine. This gives us high confidence that other APIs and libraries which use memcache also have high to perfect fidelity.

Happy caching!