Backend Development 7 min read

Proactive Cache Refresh Strategies for Memcached to Prevent Cache Stampede

This article examines various techniques for proactively refreshing Memcached entries before they expire, including dual‑key schemes, timestamp‑based checks, and lock‑based updates, and presents a preferred Java implementation that minimizes cache‑stampede and reduces memory overhead.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Proactive Cache Refresh Strategies for Memcached to Prevent Cache Stampede

When a Memcached entry expires, a sudden surge of requests can hit the database, causing a cache‑stampede problem. Instead of reacting after expiration, this article explores methods to refresh the cache shortly before it becomes stale.

Several approaches are discussed:

1. Periodically query the database and write results to Memcached

This method struggles with dynamic keys and distinguishing hot versus cold data.

2. On a cache miss, acquire a lock and let only one thread query the database

In multi‑server environments this can still lead to concurrent updates.

3. Store the expiration timestamp together with the value

When a get operation finds that now - expiration > 5s , a background task updates the cache, but serialization of timestamp and value is cumbersome.

4. Use two keys: one for the data (e.g., aaa ) and another for its expiration marker (e.g., expire_aaa )

When expire_aaa is null, a background task attempts to add the marker key (which succeeds only for the first thread) and then refreshes the data.

5. Embed the future expiration time inside the cached value and combine it with the add command to ensure a single updater

The author prefers this method because it uses only one extra key (a short‑lived lock like __load_{key} ) and avoids the memory cost of the dual‑key scheme.

A Java implementation using xmemcached is provided. The key interfaces are:

public interface DataLoader {
    public
T load();
}
public class RefreshCacheManager {
    static public
T tryGet(MemcachedClient memcachedClient, final String key, final int expire, final DataLoader dataLoader);
    static public
T autoRetryGet(MemcachedClient memcachedClient, final String key, final int expire, final DataLoader dataLoader);
}

The autoRetryGet method retries up to four times with 500 ms intervals when a null value is returned. The manager automatically detects when a cached entry is close to expiration, launches a background refresh, and ensures only one thread performs the database query.

In summary, the fifth approach—embedding timestamps and using a short‑lived lock key—is recommended for its simplicity, lower memory usage, and suitability for clustered Memcached deployments.

backendJavaConcurrencyMemcachedCache InvalidationCache Refresh
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.