Memcached

Memcached is a high-performance, distributed in-memory key-value cache designed in 2003 by Brad Fitzpatrick at LiveJournal. It is the spiritual ancestor of Redis — simpler, multi-threaded, and laser-focused on one task: caching opaque byte strings keyed by short string keys. Memcached has no persistence, no replication, no data types beyond byte strings, and no cluster mode — deliberately, because its design goal is the smallest possible cache primitive.

Key Features:

Memcached vs. Redis:

Use Cases:

4. Architecture

Cache-Aside with Client-Side Sharding App server memcache client Consistent hash key to server memcached 1 slab memory memcached 2 slab memory memcached 3 slab memory on miss Database on miss: read, then set Servers never talk to each other; the client decides where each key lives.

Memcached servers are independent: there is no replication, no cluster membership protocol, and no persistence. Distribution happens in the client library, which hashes each key to choose a server. Consistent hashing (for example the ketama scheme) means that adding or removing one server remaps only roughly 1/N of the keys instead of nearly all of them. Losing a server is treated as a burst of cache misses, which the application absorbs by reading from the database again.

5. Memory Management

Slab Allocator Item size key + value + header Slab class chunk sizes grow by factor 1 MB pages split into chunks LRU per class evict when full

To avoid fragmentation, Memcached allocates memory in 1 MB pages and divides each page into fixed-size chunks belonging to a slab class. Each class holds items of a size range, with chunk sizes growing by a configurable factor (1.25 by default). An item goes into the smallest chunk that fits, wasting the remainder. Each slab class has its own LRU, so eviction happens within a class: if most memory went to small items early on, large items may be evicted aggressively. Newer versions rebalance pages between classes automatically, which reduces this effect.

6. Worked Example: Cache-Aside in Python

sudo apt install memcached
memcached -d -m 1024 -p 11211 -U 0 -l 127.0.0.1     # 1 GB, TCP only, localhost
pip install pymemcache
echo stats | nc -q1 127.0.0.1 11211 | grep -E "get_hits|get_misses|evictions"
import json
from pymemcache.client.hash import HashClient

cache = HashClient([("10.0.0.11", 11211), ("10.0.0.12", 11211)],
                   connect_timeout=0.2, timeout=0.2, ignore_exc=True)

def get_user(user_id, db):
    key = f"user:v1:{user_id}"
    hit = cache.get(key)
    if hit is not None:
        return json.loads(hit)
    row = db.fetch_user(user_id)                  # source of truth
    cache.set(key, json.dumps(row), expire=300)   # 5-minute TTL
    return row

def update_user(user_id, fields, db):
    db.update_user(user_id, fields)
    cache.delete(f"user:v1:{user_id}")            # invalidate, do not update

ignore_exc=True makes a down cache server behave like a miss rather than an error. Deleting on write, instead of setting the new value, avoids races where two writers leave stale data in the cache.

7. When to Use Memcached

Memcached is a good fit when you need a large, simple, multi-threaded cache for opaque values, such as rendered page fragments, serialized objects, and database query results, and you can rebuild everything from the source of truth. Its multi-threaded design uses many cores on one host, and its small feature set makes behaviour predictable. Choose Redis instead when you need data structures (sorted sets, hashes, streams), persistence, replication, pub/sub, or atomic server-side operations beyond increment and compare-and-set.

8. Pitfalls