Command Palette

Search for a command to run...

Hectal
PHASE 2Intermediate ~16 min· topic 2 of 4

Topic 2.2

maxmemory and Eviction Policies

In one line

When Redis reaches maxmemory, the eviction policy decides what happens: refuse writes (noeviction), or evict keys chosen by approximated LRU, LFU, TTL or randomness, from all keys or only those with a TTL. Choosing wrong either breaks writes or silently deletes important data.

0/4 · 0%

Think of it like this

A small backpack on a long trip. When it's full you either stop picking things up (noeviction), throw out what you haven't used for longest (LRU), throw out what you use least often (LFU), or throw out whatever is going to expire soonest (volatile-ttl). Which rule is right depends on whether the backpack holds snacks or your passport.

Key ideas

  1. 01

    maxmemory sets the limit (0 means no limit on 64-bit systems, so Redis grows until the OS kills it; always set it, typically 60–80% of the machine or container memory to leave room for fork copy-on-write, buffers and fragmentation).

  2. 02

    Policies (maxmemory-policy): noeviction (default: writes that need memory fail with OOM command not allowed when used memory > 'maxmemory'; reads and deletes still work), allkeys-lru, allkeys-lfu, allkeys-random, and the volatile-* versions (volatile-lru, volatile-lfu, volatile-random, volatile-ttl) that only consider keys with a TTL. If no volatile key exists, volatile-* policies behave like noeviction.

  3. 03

    Redis's LRU is approximate: instead of a linked list over all keys, each key stores a 24-bit clock of last access. On eviction, Redis samples maxmemory-samples keys (default 5) and feeds candidates into a pool of 16, evicting the best. Sampling 10 gets very close to true LRU at slightly more CPU.

  4. 04

    LFU (Redis 4+) stores an 8-bit logarithmic access counter (Morris counter) with decay: lfu-log-factor (default 10) controls how many hits it takes to saturate, and lfu-decay-time (default 1 minute) halves counters of keys not accessed. LFU resists cache pollution from one-time scans that would flush an LRU cache.

  5. 05

    Eviction happens on the write path: before executing a command that may need memory, Redis evicts until it's under the limit. Big writes into a full instance can trigger long eviction loops ("eviction storms") and latency spikes. maxmemory-eviction-tenacity controls how much time each round may spend.

  6. 06

    Replicas ignore maxmemory by default (replica-ignore-maxmemory yes); they delete keys when the primary's evictions arrive as DELs. Keep the replica's memory at least as large as the primary's.

  7. 07

    Rule of thumb: pure cache → allkeys-lru (or allkeys-lfu for skewed popularity). Stateful data (queues, locks, sessions you can't lose) → noeviction on a separate instance, with alerts well before the limit. Mixing cache and critical data in one instance with volatile-lru works only if every cache key has a TTL and no critical key does, which is fragile.

Code & diagrams

eviction.redisredis
127.0.0.1:6379> CONFIG SET maxmemory 100mb
OK
127.0.0.1:6379> CONFIG SET maxmemory-policy noeviction
OK
# ... fill memory ...
127.0.0.1:6379> SET k "v"
(error) OOM command not allowed when used memory > 'maxmemory'.
127.0.0.1:6379> GET existing-key          # reads still work
"..."
127.0.0.1:6379> CONFIG SET maxmemory-policy allkeys-lfu
OK
127.0.0.1:6379> SET k "v"
OK
127.0.0.1:6379> OBJECT FREQ hot:key        # LFU counter (needs an LFU policy)
(integer) 21
127.0.0.1:6379> INFO stats
evicted_keys:40211
keyspace_hits:9121212
keyspace_misses:311002
policy-choice.mermaiddiagram
Rendering diagram…

Interview problem

The problem

Cache full: explain every policy

Redis reaches maxmemory. Explain what happens under each policy. Which would you choose for a pure cache? What changes if the same Redis also holds critical data such as locks, rate-limit counters and job queues?

The interviewer follows up

01

Why is Redis's LRU approximate, and does it matter?

02

What's an eviction storm and how do you avoid it?

When it breaks

maxmemory not set on a cache in a container with a 4 GB limit

What you see

Redis grows past 4 GB, the kernel OOM-kills it, and the cache (plus anything else stored there) is gone; with persistence on, it may crash-loop while reloading.

Fix & prevent

Set maxmemory to ~70–80% of the container limit and an explicit policy; monitor used_memory and RSS.

Distributed locks stored in a cache instance with allkeys-lru

What you see

Under memory pressure a lock key is evicted; a second worker acquires the lock while the first still works, and a job runs twice.

Fix & prevent

Put coordination data on a noeviction instance; use fencing tokens for correctness (Topic 12.2).

Explain it without notes

01

Explain the difference between allkeys-lru and volatile-lru, and when volatile-lru acts like noeviction.

02

Why can LFU be better than LRU for a cache?

Practice

01

In the lab, set maxmemory 20mb and allkeys-lru, load 100K keys, then read a subset repeatedly while loading more. Check which keys survive.

02

Compute hit ratio = keyspace_hits / (keyspace_hits + keyspace_misses) from INFO stats on your lab instance.

Trade-offs

  • ↔

    noeviction protects data but turns memory pressure into write errors; allkeys-* keeps writes working but silently loses data.

  • ↔

    Larger maxmemory-samples makes eviction more accurate for a little more CPU per eviction.

Done when you can

  • I can explain all eight policies and what happens at the limit under each.

  • I can choose a policy for pure cache and explain why critical data needs a separate instance.

  • I know how approximate LRU and LFU work.