CS6320:  SW Engineering of Web Based Systems

 

GAE Memcache

 

Problem= Fetching an entity from the datastore by key can take time on the order of tens of milliseconds. (scale!!!)

Solution = A memory cache uses a volatile storage medium, usually the RAM of the cache machines, for very fast read and write access to values.

 

 

GAE Solution = A distributed memory cache provides scalable, consistent temporary
storage for distributed systems, so many processes can access the same data.

 

Don't Use Memory Cache for


NOT for long term storage = it gets erased during an outage

NOT for short term storage of IMPORTANT data = again can be erased in outage

 

Google's Memory Cache = Memcache

  • named after original memcached system that it resembles

  • stores key-value pairs.

  • key size = 250 bytes

  • value = 1 MByte

Google's Memcache -- use it in "front" of datastore

cache datastore entities by their keys.

IDEA

1)Prior to a datastore Fetch ----first check the memcache for a value with that key

2) if FOUND (Cache hit) then use it

3) if NOT FOUND (Cache miss) then fetch from datastore AND put in Memcache

CONCEPT: At small expense of for cache storage in #3 follow on fetches will be faster.

BEST Practice:

1) When Data Entity changes, delete it from Memcache (note possible that delete fails and get old data
2) To minimize this possiblity give expiration time to memcache entry

 

 

Google Memcache and Python ---see official api

 

Google Memcache Java low level api

  • key = 250 bytes

  • value = serializable object max 1 MByte

  • OPTION 1 w/JPA : Entity class use @Serializable annotation

  • OPTION 2 w/Low Level Java Entity: Entity class and all of the property value classes implement the Serializable interface.

  • Classes: MemcacheServiceFactory and MemcacheService

    import com.google.appengine.api.memcache.MemcacheService;
    import com.google.appengine.api.memcache.MemcacheServiceFactory;
    
    // ...somewhere in your webapp code
       List<String> headlines;
       MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
    
       //put a new item in cache associated with string "headlines"
       memcache.put("headlines", headlines);
       headlines = (List<String>) memcache.get("headlines");

    //remove item associated with string "headlines" in cache memcache.delete("headlines");
  • MemcacheServiceObject.put(key, value)

    • key = serializable key

    • value = serializable object

  • MemcacheServiceObject.put(key, value, expiration)

    • memcache.put("headlines", headlines, Expiration.byDeltaSeconds(300)); //done in milliseconds

    • memcache.put("headlines", headlines, Expiration.onDate(instance_java_util_Date)); //based on date

  • MemcacheServiceObject.put(key, value, expiration, policy)

    • memcache.put("headlines", headlines, null, SetPolicy.ADD_ONLY_IF_NOT_PRESENT); //add only if not present

      • SetPolicy.* =

        • SET_ALWAYS (the default)

        • ADD_ONLY_IF_NOT_PRESENT (only create, do not overwrite)

        • REPLACE_ONLY_IF_PRESENT (only overwrite, do not create)

 

GAE low level Memcahce API -- checking to see if in cache

       boolean headlinesAreCached = memcache.contains("headlines");  //based on key="headlines"

GAE low level Memcahce API -- removing from cache

       memcache.delete("headlines"); //based on key="headlines"

GAE low level Memcahce API -- batching multiple fetch/set/delete operations



Multiple sets /adding to memcache

import java.util.HashMap;
import java.util.Map;
// ...
Map<Object, Object> articleSummaries = new HashMap<Object, Object>();
articleSummaries.put("article00174", "...");
articleSummaries.put("article05234", "...");
articleSummaries.put("article15820", "...");
memcache.putAll(articleSummaries);


Multiple Fetches

import java.util.List;
   // ...
   List<Object> articleSummaryKeys = Arrays.<Object>asList(
   "article00174",
   "article05234",
   "article15820");
   Map<Object, Object> articleSummaries = memcache.getAll(articleSummaryKeys);

 

Multiple deletes

import java.util.List;
    // ...
    List<Object> articleSummaryKeys = Arrays.<Object>asList(
    "article00174",
    "article05234",
    "article15820");
    memcache.deleteAll(articleSummaryKeys);

 

 

Avoiding collisions using Java low level cache API by adding NAMESPACE

Namespaces let you segment the key space by the kind of thing you are storing

To use namespaces in the low-level Java API, you set the namespace on the MemcacheService by calling its setNamespace()

 
   memcache.setNamespace("News");
   memcache.put("headlines", headlines);
   memcache.setNamespace("User");
   memcache.put("headlines", userHeadlines);


  // Get User:"headlines".
   userHeadlines = (List<String>) memcache.get("headlines");

   // Get News:"headlines".
   memcache.setNamespace("News");   //will get a memcache hit for key="headlines" only if in Newspace = "News"
   headlines = (List<String>) memcache.get("headlines");

Google Memchache Java low level api --- STATISTICS

import com.google.appengine.api.memcache.Stats;
   // ...
   Stats stats = memcache.getStatistics();
   int ageOfOldestItemMillis = stats.getMaxTimeWithoutAccess();

other statistics methods

getHitCount() = num cache hits counted.

getMissCount() = number of cache misses counted.

getItemCount() = number of items currently in the cache.

getTotalItemBytes() = total size of items currently in the cache.

getBytesReturnedForHits() = total of bytes returned in response to cache hits, including keys and values.

getMaxTimeWithoutAccess() = age of the least recently accessed item in the cache, in seconds.

 

Google AsyncMemcacheService -- perform memcache operations asynchronously

 

Google Memcache Java with JCache api -- see official api

 

Why use low level Memcache API over JCache API?

  • there are automatic increment and decrement integer counter values

  • more cache statistics, such as the amount of time since the least-recently-used entry was accessed, and the total size of all items in the cache.

  • Check and set operations to conditionally store data

  • Perform memcache operations asynchronously, using the AsyncMemcacheService.

 

 

 

© Lynne Grewe