How it works
The explanation, with examples you can run.
Expiry
> SET session:abc '{"user":42}' EX 1800OK> TTL session:abc(integer) 1800> SET session:abc '{"user":43}'OK> TTL session:abc(integer) -1The second SET wiped the TTL; -1 means the key exists with no expiry (-2 means no such key). Pass KEEPTTL to keep it, or set EX again. EXPIRE key seconds sets a TTL on an existing key, with options NX (only if it has none), XX, GT and LT; PERSIST removes it. Hash fields can have their own TTLs too, since Redis 7.4 (HEXPIRE).
Expired keys are removed in two ways: lazily, when a client touches one, and by a periodic background task that samples keys with TTLs and deletes the expired ones. So memory used by expired keys is reclaimed gradually, not exactly at the moment they expire. Give large numbers of keys slightly different TTLs (add some random seconds), or they all expire, and all miss, together.
Eviction
With maxmemory set (0, the default on 64-bit systems, means no limit), Redis checks memory before running commands that may add data. If it is over the limit, it evicts keys according to maxmemory-policy:
| Policy | Evicts |
|---|---|
noeviction (default) | Nothing; commands that would add data fail |
allkeys-lru | The least recently used keys |
allkeys-lfu | The least frequently used keys |
allkeys-random | Random keys |
volatile-lru, volatile-lfu, volatile-random | As above, but only keys that have a TTL |
volatile-ttl | Keys with a TTL, shortest remaining first |
Redis 8.6 added allkeys-lrm and volatile-lrm (least recently modified: reads do not count as use). With the default policy and a full instance:
> SET one-more value(error) OOM command not allowed when used memory > 'maxmemory'.For a cache, allkeys-lru is a sound default; allkeys-lfu does better when a stable set of keys is popular over time. INFO stats reports evicted_keys, worth watching: steady eviction means the cache is smaller than its working set.
Approximate LRU
Tracking exact recency for millions of keys would cost memory and time. Instead, Redis samples a few keys (maxmemory-samples, default 5) and evicts the best candidate among them, keeping a small pool of good candidates between evictions. This toy compares exact LRU with sampling on a workload where 80% of requests go to 50 hot keys:
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
Five samples get within a couple of points of exact LRU here; one sample is just random eviction. Raising maxmemory-samples gets closer to exact LRU, at the cost of more CPU per eviction.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.