Databases 7 min read

Mastering Redis Expiration: Strategies, Java Implementation, and Best Practices

Redis uses multiple expiration and eviction mechanisms—including lazy deletion, periodic scanning, and memory eviction—to balance performance and memory usage, and this guide explains each strategy, shows how to configure them, and provides Java/Jedis code examples for setting TTLs, handling large objects, preventing cache avalanches, and monitoring stats.

Ray's Galactic Tech
Ray's Galactic Tech
Ray's Galactic Tech
Mastering Redis Expiration: Strategies, Java Implementation, and Best Practices

Why Expiration Keys Are Needed

Redis is an in‑memory database; unlimited growth would exhaust memory, so it provides key expiration and deletion mechanisms to keep memory usage under control. Common use cases include verification codes, temporary caches, session/token management, cache‑avalanche protection, and hotspot control.

Three Expiration Deletion Strategies

Timed Deletion – Keys are removed exactly when a timer expires. Advantage: immediate memory release. Disadvantage: high CPU usage. Not used by Redis.

Lazy Deletion – Keys are checked and deleted only when accessed by a client. Advantage: CPU‑friendly. Disadvantage: possible memory waste. Redis adopts this.

Periodic Deletion – A background thread randomly samples a subset of keys at intervals. Advantage: balances CPU and memory. Disadvantage: tuning parameters can be complex. Redis also uses this.

Memory Eviction – When memory is insufficient, Redis evicts keys according to a maxmemory‑policy (e.g., allkeys‑lru). This complements the above strategies.

How Redis Implements Deletion

In practice Redis combines lazy deletion and periodic deletion , and triggers the eviction policy when memory runs low.

Setting Expiration in Java (Jedis)

Jedis jedis = new Jedis("localhost", 6379);
// 1. Set value with expiration (seconds)
jedis.setex("user:1001", 60, "Tom");

// 2. Set expiration in milliseconds
jedis.psetex("user:1002", 3000, "Jerry");

// 3. Add expiration to an existing key
jedis.set("order:12345", "pending");
jedis.expire("order:12345", 3600); // 1 hour

// 4. Query remaining TTL
System.out.println("TTL user:1001 = " + jedis.ttl("user:1001"));

Lazy Deletion Example

jedis.setex("temp:data", 5, "123"); // 5‑second TTL
Thread.sleep(6000);
String val = jedis.get("temp:data"); // null, Redis auto‑deletes
System.out.println("Value after expire: " + val);

Periodic Deletion Example

Redis background thread scans a fraction of keys periodically. Statistics can be viewed with INFO stats, which includes expired_keys and evicted_keys.

String info = jedis.info("stats");
System.out.println(info); // contains expired_keys, evicted_keys, etc.

To adjust the scan frequency, modify hz in redis.conf (default 10, increase to 50 for more frequent checks).

Large Object Deletion: DEL vs UNLINK

DEL – Synchronous deletion, may block Redis.

UNLINK – Asynchronous deletion, recommended for large objects.

// Build a large hash
for (int i = 0; i < 100000; i++) {
    jedis.hset("big:hash", "field" + i, String.valueOf(i));
}
// Asynchronous delete (recommended)
jedis.unlink("big:hash");

Cache‑Avalanche Protection (Randomized TTL)

import java.util.Random;
Random rand = new Random();
int ttl = 300 + rand.nextInt(60); // 300‑360 seconds
jedis.setex("cache:user:1001", ttl, "cached-data");

Session / Token Management Example

// Generate token (30‑minute TTL)
String token = "abcd1234";
jedis.setex("token:" + token, 1800, "user:1001");

// Validate token
String userId = jedis.get("token:" + token);
if (userId != null) {
    System.out.println("Token valid, userId = " + userId);
} else {
    System.out.println("Token expired");
}

Monitoring Expiration and Eviction

String stats = jedis.info("stats");
for (String line : stats.split("
")) {
    if (line.contains("expired_keys") || line.contains("evicted_keys")) {
        System.out.println(line.trim());
    }
}

Typical output:

expired_keys:12034
evicted_keys:456

Key Takeaways

Use SETEX for short‑lived data; lazy deletion suffices.

For high‑concurrency caches, add random jitter to TTL to avoid avalanche.

Prefer UNLINK over DEL for large objects.

Redis’s built‑in expiration fits session and token management naturally.

Configure an appropriate maxmemory-policy (e.g., allkeys‑lru) for production.

Regularly monitor expired_keys and evicted_keys metrics.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaCacheredisJedisTTLExpiration
Ray's Galactic Tech
Written by

Ray's Galactic Tech

Practice together, never alone. We cover programming languages, development tools, learning methods, and pitfall notes. We simplify complex topics, guiding you from beginner to advanced. Weekly practical content—let's grow together!

0 followers
Reader feedback

How this landed with the community

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.