Chapter 18 · Memory Management, Eviction, Expiration, Fragmentation, and OOM Prevention

Approximate LRU/LFU Sampling, LFU Decay, Hot-Set Behavior, and Cache Hit Rate

Understand Redis approximate LRU/LFU sampling, LFU decay and probabilistic counters, then measure hot-set survival and cache hit rate under controlled pressure.

Advanced180–250 minutesapproximate LRU/LFU, sampling, decay, hit rateRedis Open Source 8.10.1Docker + redis-py 8.1.0Free/local-firstLast reviewed: September 6, 2026

Learning outcomes

AtlasMart has a small hot set of products and a long cold tail. The team wants “perfect LRU,” but perfect global ordering would itself consume CPU/memory. Redis instead samples candidates and uses compact metadata, so the useful question is whether the approximation preserves the workload's valuable working set.

01

Explain sampled LRU and why maxmemory-samples changes accuracy/CPU cost rather than correctness semantics.

02

Explain LFU probabilistic counters, lfu-log-factor, and decay.

03

Use OBJECT FREQ and OBJECT IDLETIME only under policies where they are valid.

04

Measure cache hit rate and hot-set survival under deterministic skew.

05

Avoid treating one key's metadata as a guarantee of exact eviction order.

Exact Chapter 18 lab boundary

The course baseline remains Redis Open Source 8.10.1 from pinned image redis:8.10.1. Memory-pressure experiments use dedicated disposable Chapter 18 containers, named volumes, and loopback-only host ports 6391–6395 so the shared Chapter 01 lab is never pushed toward eviction or out-of-memory behavior. The temporary academy-admin password is classroom-only. TLS is omitted only on loopback. Mandatory topology is standalone, logical DB 0. Each lesson states its own persistence, maxmemory, eviction, and container-memory settings. Lesson 3 uses a 24 MiB maxmemory node with persistence disabled. The fixture is intentionally small and records actual results rather than claiming a universal best sample size.

1. LRU is sampled, not a global exact list

Redis LRU samples a small number of keys, keeps good candidates, and evicts among those candidates rather than maintaining a perfect ordering of every key. maxmemory-samples controls the sample count. Larger samples can more closely approximate ideal LRU but consume additional CPU during eviction.

Correct interpretation

“Key A is older than key B” does not guarantee A is the next key evicted. The policy is probabilistic at the candidate-selection level.

2. Start with LFU and inspect its knobs

Shell · create one isolated memory node
docker volume create atlasmart-redis-ch18-policy_datadocker run --rm -v atlasmart-redis-ch18-policy_data:/data redis:8.10.1 sh -lc 'printf "%s\n" "user default off" "user academy-admin on >AtlasMart-Admin-Lab-Only-2026 ~* &* +@all" > /data/users.acl'docker run -d --name atlasmart-redis-ch18-policy --memory 192m -p 127.0.0.1:6393:6379 -v atlasmart-redis-ch18-policy_data:/data redis:8.10.1 redis-server --dir /data --aclfile /data/users.acl --save '' --appendonly no --maxmemory 24mb --maxmemory-policy allkeys-lfu --maxmemory-samples 5 --lfu-log-factor 10 --lfu-decay-time 1docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin PINGdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin ACL WHOAMI
redis-cli · current policy metadata
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin CONFIG GET maxmemory maxmemory-policy maxmemory-samples lfu-log-factor lfu-decay-timedocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin INFO statsdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin INFO memory

3. LFU stores a compact probabilistic frequency estimate

LFU uses a logarithmic Morris-style counter rather than an exact request count, then decays old popularity over time. The default lfu-log-factor 10 controls counter growth and lfu-decay-time 1 means one-minute decay intervals when sampled. The counter is an eviction heuristic—not an analytics metric.

Python · deterministic hot/warm/cold access skew
import os, redisHOST = "127.0.0.1"PORT = 6393r = redis.Redis(host=HOST, port=PORT, username="academy-admin", password="AtlasMart-Admin-Lab-Only-2026", decode_responses=False)assert r.ping()import randomrng = random.Random(1803)payload = b"v" * 16384for i in range(500): r.set(f"atlasmart:ch18:l3:item:{i}", payload)hot = list(range(20))warm = list(range(20, 100))for _ in range(6000):    x = rng.random()    if x < 0.75: i = rng.choice(hot)    elif x < 0.95: i = rng.choice(warm)    else: i = rng.randrange(100, 500)    r.get(f"atlasmart:ch18:l3:item:{i}")print("hot_freq", [r.object("freq", f"atlasmart:ch18:l3:item:{i}") for i in range(5)])print("cold_freq", [r.object("freq", f"atlasmart:ch18:l3:item:{i}") for i in range(450,455)])
redis-cli · LFU-only evidence
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin OBJECT FREQ atlasmart:ch18:l3:item:0docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin OBJECT FREQ atlasmart:ch18:l3:item:450docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin --hotkeys --pattern "atlasmart:ch18:l3:*" --count 100

4. OBJECT FREQ and IDLETIME are policy-specific diagnostics

OBJECT FREQ is available only under LFU policies. OBJECT IDLETIME is unavailable when the maxmemory policy is LFU because the compact object metadata is used for LFU frequency instead. Always verify policy before interpreting either command.

redis-cli · prove the command boundary
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin OBJECT FREQ atlasmart:ch18:l3:item:0docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin OBJECT IDLETIME atlasmart:ch18:l3:item:0# Under an LFU policy, OBJECT IDLETIME should report that it is unavailable.

5. Pressure the cache and measure population-level outcomes

The right test is not “did the mathematically oldest key disappear?” It is “under this reproducible access distribution and memory pressure, did the policy preserve the hot working set and deliver an acceptable miss/latency profile?”

Python · bounded LFU pressure and hit-rate probe
import os, redisHOST = "127.0.0.1"PORT = 6393r = redis.Redis(host=HOST, port=PORT, username="academy-admin", password="AtlasMart-Admin-Lab-Only-2026", decode_responses=False)assert r.ping()stats0 = r.info("stats")hits0, misses0 = stats0["keyspace_hits"], stats0["keyspace_misses"]payload = b"n" * 16384for i in range(500, 1800): r.set(f"atlasmart:ch18:l3:item:{i}", payload)alive_hot = sum(r.exists(f"atlasmart:ch18:l3:item:{i}") for i in range(20))alive_cold = sum(r.exists(f"atlasmart:ch18:l3:item:{i}") for i in range(450,500))for i in range(20): r.get(f"atlasmart:ch18:l3:item:{i}")for i in range(450,500): r.get(f"atlasmart:ch18:l3:item:{i}")stats1 = r.info("stats")dh = stats1["keyspace_hits"] - hits0dm = stats1["keyspace_misses"] - misses0print("hot_alive", alive_hot, "of 20", "cold_alive", alive_cold, "of 50")print("probe_hit_rate", dh / max(1, dh + dm), "evicted_keys", stats1["evicted_keys"])
Do not overfit this lab

This fixture is not a production benchmark. Real hit rate depends on request skew, object-size distribution, TTLs, pipeline/concurrency, sample size, and client/server topology.

6. Change maxmemory-samples only as an experiment

The default sample count is a deliberate efficiency tradeoff. Increasing it can make LRU/LRM candidate selection closer to an ideal ordering, but more sampling adds CPU work. For LFU, sampling is only one part of behavior; the logarithmic counter and decay parameters also matter.

redis-cli · record, change, and restore a bounded test value
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin CONFIG GET maxmemory-samplesdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin CONFIG SET maxmemory-samples 10docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin CONFIG GET maxmemory-samplesdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch18-policy redis-cli --user academy-admin CONFIG SET maxmemory-samples 5
Production rule

Change one parameter at a time and compare hit/miss distribution and tail latency. Do not copy a universal sample count from a benchmark.

7. LFU decay is adaptation, not a timer that resets counters exactly

Decay prevents yesterday's hot key from staying protected forever. Redis applies decay as keys participate in the LFU mechanism; lfu-decay-time should not be interpreted as a background scheduler that resets every counter at an exact wall-clock boundary. A value of zero disables decay.

Setting Meaning Risk if misread
lfu-log-factor Controls how quickly the probabilistic counter grows/saturates. Treating FREQ as exact request count.
lfu-decay-time Minutes controlling frequency decay when relevant metadata is sampled. Assuming synchronized periodic decrements for every key.
maxmemory-samples Candidate sample count for approximate eviction. Assuming larger is always better regardless of CPU/tail latency.

8. Redis 8.6+ LRM is a separate question

Least Recently Modified (LRM) was added in Redis 8.6. It tracks write recency rather than read+write access recency. That can be useful for read-heavy datasets where frequently read but stale values should still be considered old. It is not a replacement for LRU or LFU; it expresses a different notion of value.

9. Verification checklist

  • Confirm policy before using OBJECT FREQ or OBJECT IDLETIME.
  • Capture frequency counters as heuristic metadata, not exact request counts.
  • Measure keyspace_hits/keyspace_misses deltas and evicted_keys.
  • Compare hot-set and cold-tail survival under the same deterministic trace.
  • Do not change LFU decay/log-factor or sample size without latency and workload evidence.
Shell · bounded cleanup
docker rm -f atlasmart-redis-ch18-policydocker volume rm atlasmart-redis-ch18-policy_data# Removes only this named Chapter 18 node and volume.

Check your understanding

  1. Why does Redis approximate LRU instead of maintaining a perfect global order?
  2. Is OBJECT FREQ an exact access count?
  3. Why is OBJECT IDLETIME unavailable under LFU?
  4. What should decide maxmemory-samples?
Review the answers

Approximation greatly reduces metadata and CPU cost while preserving useful recency behavior for common workloads.

No. LFU uses a logarithmic probabilistic counter with decay; it is an eviction heuristic.

The compact per-key metadata used for idle-time/LRU tracking is repurposed for LFU frequency state.

Measured hit/miss behavior and latency/CPU under the real access and object-size distribution, not a universal number.

Production judgment and next bridge

Cache quality is a distribution-level property. Measure hit rate, tail latency, evictions, skew, and memory together. Lesson 4 moves from policy heuristics to pathological shapes: big keys, hot keys, asynchronous freeing, fragmentation, and active defrag diagnostics.

Summary and next step

Approximate LRU/LFU Sampling, LFU Decay, Hot-Set Behavior, and Cache Hit Rate is now connected to observable Redis behavior, bounded failure cases, and production tradeoffs. Keep the evidence and cleanup state from this lesson; next, continue with Big Keys, Hot Keys, Large Collections, Lazy Freeing, Active Defrag, and Memory Diagnostics.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.