Databases 12 min read

Understanding Redis Expiration and Eviction Policies

This article explains how Redis handles key expiration, the commands for setting TTL, the three expiration strategies, the eight memory‑eviction policies, and the internal LRU and LFU algorithms used to manage hot data when memory is exhausted.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Understanding Redis Expiration and Eviction Policies

When a Redis server runs out of memory, it must decide how to handle further commands; this article describes the mechanisms Redis provides for key expiration and memory eviction.

Expiration commands : Redis offers four commands to set a key’s time‑to‑live – expire key ttl (seconds), pexpire key ttl (milliseconds), expireat key timestamp (seconds), and pexpireat key timestamp (milliseconds). The set command can also set an expiration atomically. The remaining time can be queried with ttl and pttl .

Expiration strategies : Redis combines two strategies – lazy deletion (checking expiration on access) and periodic scanning (a background task that scans keys with an expiration). Timed deletion (a timer per key) is not used because of CPU overhead.

Eviction policies : When memory is full and no keys have an expiration, Redis uses the maxmemory setting and one of eight maxmemory-policy options to decide which keys to evict:

volatile‑lru – LRU on keys with an expiration

allkeys‑lru – LRU on all keys

volatile‑lfu – LFU on keys with an expiration

allkeys‑lfu – LFU on all keys

volatile‑random – random eviction of keys with an expiration

allkeys‑random – random eviction of any key

volatile‑ttl – evict keys that will expire soonest

noeviction – reject writes when memory is exhausted

These policies can be changed at runtime with config set maxmemory-policy <policy> .

LRU implementation : Redis does not store a full timestamp for each key. Instead, each object has a 24‑bit lru field updated by a global lru_clock (incremented every 100 ms by serverCron ). Eviction selects keys with the largest difference between lru_clock and the object's lru . Sampling (default 5 keys) is used to reduce overhead.

typedef struct redisDb {
    dict *dict;               // all key‑value pairs
    dict *expires;            // keys with an expiration
    dict *blocking_keys;     // blocked keys (e.g., BLPOP)
    dict *watched_keys;      // WATCHed keys
    int id;                  // database ID
    // ... other fields omitted
} redisDb;

LFU implementation : The high 16 bits of the 24‑bit lru field store the last decrement time, and the low 8 bits store a logarithmic counter (max 255). The counter increments probabilistically based on lfu_log_factor (default 10). The counter decays over time according to lfu-decay-time (default 1 minute), calculated from the difference between the current timestamp (in minutes) and the stored time.

lfu_log_factor 10
lfu-decay-time 1

Both LRU and LFU are approximate algorithms designed for high performance, avoiding per‑key system calls and large memory overhead.

Summary : The article covers how Redis sets key expirations, the three expiration handling strategies, the eight eviction policies for out‑of‑memory situations, and the internal LRU/LFU mechanisms that enable efficient memory management.

Memory ManagementRedisLRULFUEvictionexpiration
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.