Memcached’s verbose commands are not just for show; they’re the secret handshake that reveals the daemon’s inner thoughts, letting you peek behind the curtain of a seemingly opaque cache.

Let’s see it in action. Imagine you’re troubleshooting a sluggish application and suspect Memcached is the bottleneck. You connect to your Memcached instance, typically on port 11211, and start issuing commands.

telnet localhost 11211

Once connected, instead of just get key, you’ll use get with a modifier. For instance, to see exactly how Memcached processes a get request, including which slab it checks and if it finds a hit or miss, you can use a hypothetical verbose get (Memcached doesn’t have a direct verbose get command, but we’ll simulate the type of insight we’re looking for).

Let’s consider a common diagnostic scenario: a cache hit rate that’s unexpectedly low.

Debugging Low Cache Hit Rate

The core issue is that your application is requesting data from Memcached, but the cache isn’t returning it as often as it should, forcing the application to fetch from the slower primary data store.

Here are the most common culprits and how to diagnose them:

  1. Keyspace Collisions (Hash Collisions): Different keys are hashing to the same internal bucket, leading to premature eviction or incorrect lookups.

    • Diagnosis: This is hard to spot directly with standard commands. You’d typically infer this from a high eviction rate coupled with seemingly random cache misses for keys that should be present. If you have access to Memcached’s internal statistics (which can be enabled via specific compile-time flags or certain forks), you might see uneven distribution of keys across slabs. For standard memcached, you can monitor evictions and curr_items over time. A sudden spike in evictions while curr_items stays relatively stable can indicate this.
    • Fix: Redesign your key naming strategy. Aim for longer, more unique keys that are less likely to collide. For example, instead of user:123:profile and user:123:settings, ensure a more robust prefixing or hashing scheme if you’re generating keys programmatically. The fix is in your application’s key generation logic.
    • Why it works: Better key distribution spreads data more evenly across Memcached’s internal hash table, reducing the chance of two distinct items being mapped to the same storage slot, thus preventing one from overwriting or obscuring the other.
  2. Keys Expiring Too Quickly: Data is being set with short TTLs (Time To Live) and expiring before the application can reasonably expect to retrieve it.

    • Diagnosis: Monitor the expi statistic. While memcached doesn’t expose expi directly in stats, you can infer it if your application sets TTLs and you see items disappearing faster than expected. If you set a key with set key 0 60 (expire in 60 seconds) and it’s gone in 30, something is wrong. You can also use get key and check the response; if it’s a miss, and you know it was recently set, expiration is a prime suspect.
    • Fix: Review your application’s logic for setting expiration times. If you’re setting a TTL of 60 seconds, ensure this is indeed what your application is doing. The fix is in the set command’s TTL parameter. For example, to keep an item for 5 minutes, use set mykey 0 300 value.
    • Why it works: Increasing the TTL allows data to persist in the cache for longer durations, increasing the probability that subsequent requests will find a cache hit.
  3. Memory Limits Reached and Evictions: Memcached has run out of memory and is aggressively evicting items to make space for new ones.

    • Diagnosis: Use the stats command and look for evictions. If this number is high and steadily increasing, Memcached is evicting items. Also, check limit_maxbytes to see the configured memory limit.
    • Fix: Increase the memory allocated to Memcached. If you started Memcached with memcached -m 64 (64MB), you might need to increase it. For example, memcached -m 128 allocates 128MB.
    • Why it works: Providing more memory allows Memcached to store more items without needing to evict existing ones, directly improving the hit rate for data that is still relevant.
  4. Incorrect Key Naming/Typing in Application: The application is setting a key with one name but trying to retrieve it with a slightly different one.

    • Diagnosis: This is often a debugging session with your application code. However, you can use stats items (if available in your memcached version/fork, or by querying specific slab stats) to see item counts per slab. If you set an item and stats items shows it, but a subsequent get for the same key results in a miss, the issue is likely in the get operation’s key. You can also use gets which returns a CAS identifier; if the CAS identifier changes between gets, it means the item was updated or evicted.
    • Fix: Standardize your key naming conventions in your application code. Ensure consistent casing, prefixes, and suffixes for all keys. The fix is code-level.
    • Why it works: Memcached performs exact string matching for keys. Any discrepancy, no matter how small, will result in a cache miss, as Memcached won’t recognize the requested key.
  5. Connection Issues / Network Latency: The application cannot reliably connect to Memcached, or the network is too slow, leading to timeouts and perceived misses.

    • Diagnosis: Check Memcached’s logs for connection errors. Use netstat -tulnp | grep 11211 to ensure Memcached is listening on the correct interface and port. Monitor network latency between your application server and Memcached server using ping or mtr.
    • Fix: Ensure Memcached is bound to the correct IP address (-l flag) and that firewalls aren’t blocking port 11211. Optimize network routes if latency is high. The fix might involve memcached -l 192.168.1.100 to bind to a specific IP, or network configuration changes.
    • Why it works: Reliable and fast network communication is essential for cache lookups. If requests can’t reach Memcached or take too long, the application will default to fetching from the primary data store.
  6. Overly Aggressive LRU (Least Recently Used) Eviction: While LRU is a fundamental eviction policy, if your access patterns are highly spiky, items might be evicted prematurely even if they are frequently accessed overall, but not recently.

    • Diagnosis: This is a subtler issue. If you’re seeing high get_misses and evictions but curr_items is well below limit_maxbytes, and your key distribution seems fine, your access pattern might be the culprit. There isn’t a direct memcached command to diagnose this specifically, but it’s a process of elimination.
    • Fix: Consider larger memory allocation to give LRU more room, or more sophisticated caching strategies outside of plain Memcached (e.g., application-level caching with different eviction policies or tiered caching).
    • Why it works: A larger cache means items stay in the LRU queue for longer, making them less susceptible to eviction by newer, even if temporarily popular, items.

After fixing these issues, the next error you’ll likely encounter is a surge in set operations as your application aggressively repopulates the now-effective cache.

Want structured learning?

Take the full Memcached course →