Skip to content
ludoch edited this page Apr 15, 2026 · 2 revisions

Using Memcache

This page describes how to configure and monitor the memcache service for your application using the Google Cloud console. It also describes how to use the App Engine memcache Go API to set and retrieve cached values.

It also describes how to use the App Engine Memcache PHP API to set and retrieve cached values.

It also describes how to do common tasks using the JCache interface and how to handle concurrent writes using the low-level App Engine memcache API for Java.

It also describes how to use the App Engine memcache Python API to set and retrieve cached values and use the compare-and-set feature to handle concurrent write requests to the same memcache key. To learn more about memcache, read the Memcache Overview.

Configure memcache

  1. Go to the Memcache page in the Google Cloud console.
    Go to the Memcache page
  2. Select the memcache service level you want to use:
    • Shared (default) - free and provides cache capacity on a best-effort basis.
    • Dedicated - billed by the GB-hour of cache size and provides a fixed cache capacity assigned exclusively to your application.

Learn more about available service classes in Memcache Overview.

Cache and retrieve values

Cache a value

Use Add() to write a value for a key if and only if no value already exists for the key:

item := &memcache.Item{
        Key:   "[KEY]",
        Value: []byte("[VALUE]"),
}
memcache.Add(c, item)

where c is an appengine.Context.

Learn more about Add and other functions for setting values in Memcache API Reference.

Look up cached values

Use Get() to get the item for a given key:

memcache.Get(ctx, "[KEY]")

Learn more about Get and other functions for looking up values in Memcache API Reference.

Example

The following example demonstrates how to add, set, and get Memcache values using the Go API.

Assume that ctx is an appengine.Context.

Use JCache

The App Engine Java SDK supports the JCache interface (JSR 107) for accessing memcache. The interface is included in the javax.cache package.

With JCache, you can set and get values, control how values expire from the cache, inspect the contents of the cache, and get statistics about the cache. You can also use "listeners" to add custom behavior when setting and deleting values.

The App Engine implementation tries to implement a loyal subset of the JCache API standard. For more information about JCache, see JSR 107. However, instead of using JCache, you may want to consider using the low-level Memcache API to access more features of the underlying service.

Geta cache instance

You use an implementation of the javax.cache.Cache interface to interact with the cache. You obtain a Cache instance using a CacheFactory, which you obtain from a static method on the CacheManager. The following code gets a Cache instance with the default configuration:

import java.util.Collections;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
import javax.cache.CacheManager;

// ...
        Cache cache;
        try {
            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
            cache = cacheFactory.createCache(Collections.emptyMap());
        } catch (CacheException e) {
            // ...
        }

The CacheFactory's createCache() method takes a Map of configuration properties. These properties are discussed below. To accept the defaults, give the method an empty Map.

Put and get values

The Cache behaves like a Map: You store keys and values using the put() method, and retrieve values using the get() method. You can use any Serializable object for either the key or the value.

String key;      // ...
        byte[] value;    // ...

        // Put the value into the cache.
        cache.put(key, value);

        // Get the value from the cache.
        value = (byte[]) cache.get(key);

To put multiple values, you can call the putAll() method with a Map as its argument.

To remove a value from the cache (to evict it immediately), call the remove() method with the key as its argument. To remove every value from the cache for the application, call the clear() method.

The containsKey() method takes a key and returns a boolean (true or false) to indicate whether a value with that key exists in the cache. The isEmpty() method tests whether the cache is empty. The size() method returns the number of values currently in the cache.

Configure expiration

By default, all values remain in the cache as long as possible, until evicted due to memory pressure, removed explicitly by the app, or made unavailable for another reason (such as an outage). The app can specify an expiration time for values, a maximum amount of time the value will be available. The expiration time can be set as an amount of time relative to when the value is set, or as an absolute date and time.

You specify the expiration policy using configuration properties when you create the Cache instance. All values put with that instance use the same expiration policy. For example, to configure a Cache instance to expire values one hour (3,600 seconds) after they are set:

import java.util.HashMap;
import java.util.Map;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
import javax.cache.CacheManager;
import javax.concurrent.TimeUnit;
import com.google.appengine.api.memcache.jsr107cache.GCacheFactory;

// ...
        Cache cache;
        try {
            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
            Map<Object, Object> properties = new HashMap<>();
            properties.put(GCacheFactory.EXPIRATION_DELTA, TimeUnit.HOURS.toSeconds(1));
            cache = cacheFactory.createCache(properties);
        } catch (CacheException e) {
            // ...
        }

The following properties control value expiration:

  • GCacheFactory.EXPIRATION_DELTA: expire values the given amount of time relative to when they are put, as an Integer number of seconds
  • GCacheFactory.EXPIRATION_DELTA_MILLIS: expire values the given amount of time relative to when they are put, as an Integer number of milliseconds
  • GCacheFactory.EXPIRATION: expire values at the given date and time, as a java.util.Date

Configure the set policy

By default, setting a value in the cache adds the value if there is no value with the given key, and replaces a value if there is a value with the given key. You can configure the cache to only add (protect existing values) or only replace values (do not add).

import java.util.HashMap;
import java.util.Map;
import com.google.appengine.api.memcache.MemcacheService;

// ...
        Map<Object, Object> properties = new HashMap<>();
        properties.put(MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT, true);

The following properties control the set policy:

  • MemcacheService.SetPolicy.SET_ALWAYS: add the value if no value with the key exists, replace an existing value if a value with the key exists; this is the default
  • MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT: add the value if no value with the key exists, do nothing if the key exists
  • MemcacheService.SetPolicy.REPLACE_ONLY_IF_PRESENT: do nothing if no value with the key exists, replace an existing value if a value with the key exists

Retrieve cache statistics

The app can retrieve statistics about its own use of the cache. These statistics are useful for monitoring and tuning cache behavior. You access statistics using a CacheStatistics object, which you get by calling the Cache's getCacheStatistics() method.

Available statistics include the number of cache hits (gets for keys that existed), the number of cache misses (gets for keys that did not exist), and the number of values in the cache.

import javax.cache.CacheStatistics;

        CacheStatistics stats = cache.getCacheStatistics();
        int hits = stats.getCacheHits();
        int misses = stats.getCacheMisses();

The App Engine implementation does not support resetting the hit and miss counts, which are maintained indefinitely but may be reset due to transient conditions of the memcache servers.

Import the Memcache API

To use Memcache for PHP, you need to add an explicit declaration of the Memcache libraries.

use Google\AppEngine\Api\Memcache\Memcache;

See the Access legacy bundled services for more details.

Cache and retrieving values

Cache a value

Use Memcache::set to add a key's value:

Look up cached values

Use Memcache::get to look up the value of a single key:

Cache and retrieve values

Cache a value

Use add() to add a key's value if and only if it doesn't already exist, with an optional expiration time:

memcache.add(key="[KEY]", value="[VALUE]", time=[EXPIRATION_TIME])

For example, to add the value raining to the key weather_USA_98105 with an expiration time of one hour from when the value is written:

memcache.add(key="weather_USA_98105", value="raining", time=3600)

Learn more about add() and other methods for setting values in the memcache Python API documentation.

See other examples of caching values in Memcache Examples.

Look up cached values

Use get() to look up the value of a single key:

memcache.get(key="[KEY]")

For example, to get the value of the key weather_USA_98105:

memcache.get(key="weather_USA_98105")

Learn more about get() and other methods for looking up values in the memcache Python API documentation.

Monitor memcache in the Google Cloud console

  1. Go to the Memcache page in the Google Cloud console.
    Go to the Memcache page

  2. Look at the following reports:

    • Memcache service level: Shows if your application is using the Shared or Dedicated service level. If you are an owner of the project, you can switch between the two. Learn more about the service levels.
    • Hit ratio: Shows the percentage of data requests that were served from the cache, as well as the raw number of data requests that were served from the cache.
    • Items in the cache.
    • Oldest item age: The age of the oldest cached item. Note that the age of an item is reset every time it is used, either read or written.
    • Total cache size.
  3. You can take any of the following actions:

    • New key: Add a new key to the cache.
    • Find a key: Retrieve an existing key.
    • Flush cache: Remove all the key-value pairs from the cache.
  4. (Dedicated memcache only) Look through the list of Hot keys.

    • "Hot keys" are keys that receive more than 100 queries per second (QPS) in the memcache.
    • This list includes up to 100 hot keys, sorted by highest QPS.

Handle concurrent writes

If you're updating the value of a memcache key that might receive other concurrent write requests, you must use the low-level memcache methods putIfUntouched and getIdentifiable instead of put and get. The methods putIfUntouched and getIdentifiable avoid race conditions by allowing multiple requests that are being handled concurrently to update the value of the same memcache key atomically.

The code snippet below shows one way to safely update the value of a key that might have concurrent update requests from other clients:

View MemcacheConcurrentServlet.java on GitHub (region: example)

Note: These methods are also available in the AsyncMemcacheService.

A refinement you could add to this sample code is to set a limit on the number of retries, to avoid blocking for so long that your App Engine request times out.

Handle concurrent writes

To use the compare and set feature to handle writes from multiple requests to the same memcache key:

  1. Instantiate a memcache Client object.
  2. Use a retry loop (preferably with a limit on the number of retries and using exponential backoff)
    1. Within the retry loop, get the key using gets() or get_multi() with the for_cas parameter set to True.
    2. Within the retry loop, update the key value using cas() or cas_multi().

The following snippet shows one way to use the compare and set feature:

The retry loop is necessary because without the loop this code doesn't actually avoid race conditions, it just detects them! The memcache service guarantees that when used in the pattern shown here (that is, using gets() and cas()), if two (or more) different client instances happen to be involved in a race condition, only the first one to execute the cas() operation succeeds (return True), while the second one (and subsequent ones) fails (return False).

Another refinement you should add to this sample code is to set a limit on the number of retries, to avoid an infinite loop in worst-case scenarios where there is a lot of contention for the same counter. An example of when such contention could occur is if there are more requests trying to update the counter than the memcache service can process in real time.

Learn more about compare and set in the Memcache Overview.

What's next

Clone this wiki locally