Databases 12 min read

Redis Key Design, Command Usage, and Client Best Practices

This guide presents comprehensive best‑practice recommendations for designing Redis keys, choosing appropriate data types, managing key lifecycles, safely using commands, optimizing client connections, handling big keys, and selecting eviction policies to ensure high performance and reliability in production environments.

Java Captain
Java Captain
Java Captain
Redis Key Design, Command Usage, and Client Best Practices

1. Key Design

1.1 Key Naming

(1) Recommendation : prioritize readability and manageability by prefixing keys with the business or database name and separating parts with colons, e.g., business:table:id .

ugc:video:1

(2) Recommendation : keep keys concise while preserving semantics; shorter keys reduce memory overhead. Example transformation:

user:{uid}:friends:messages:{mid} → u:{uid}:fr:m:{mid}

(3) Requirement : avoid special characters such as spaces, line breaks, quotes, or escape sequences.

1.2 Value Design

(1) Requirement : reject big keys to prevent network congestion and slow queries. Keep string values under 10 KB and limit collection sizes (hash, list, set, zset) to ≤ 5 000 elements.

(2) Recommendation : select the most suitable Redis data type for the entity, balancing memory encoding (e.g., ziplist) with performance.

Correct example using HMSET :

hmset user:1 name tom age 19 favor football

1.3 Key Lifecycle Management

Set expiration times with EXPIRE (preferably staggered to avoid mass expirations) and monitor idle time for non‑expiring keys.

2. Command Usage

2.1 O(N) Commands

Commands like HGETALL , LRANGE , SMEMBERS , ZRANGE , SINTER are usable but require awareness of the N value; prefer HSCAN , SSCAN , ZSCAN for large collections.

2.2 Disable Dangerous Commands

Prohibit KEYS , FLUSHALL , FLUSHDB in production via Redis' rename-command or by using progressive SCAN alternatives.

2.3 Select Command

Redis multiple databases are weakly supported; avoid relying on them as they share a single thread and can cause interference.

2.4 Batch Operations

Use native batch commands ( MGET , MSET ) or pipelines for higher throughput. Keep batch size reasonable (e.g., ≤ 500 elements, depending on payload size).

Differences:

1. Native commands are atomic; pipeline is non‑atomic.
2. Pipeline can bundle different commands.
3. Pipeline requires client and server support.

2.5 Transactions

Redis transactions are limited (no rollback) and, in clustered mode, all keys in a transaction must reside in the same slot (use hashtags to co‑locate keys).

2.6 Lua Scripts in Cluster

All keys must be passed via the KEYS array; otherwise the script fails.

All keys must belong to a single slot; otherwise an error is returned.

2.7 MONITOR Command

Use MONITOR sparingly; prolonged usage can impact performance.

3. Client Usage

3.1 Instance Isolation

Avoid sharing a single Redis instance among multiple applications; separate business domains and expose shared data via services.

3.2 Connection Pooling (Java Jedis Example)

Jedis jedis = null;
try {
    jedis = jedisPool.getResource();
    // execute commands
    jedis.executeCommand();
} catch (Exception e) {
    logger.error("op key {} error: " + e.getMessage(), key, e);
} finally {
    // return to pool, not close
    if (jedis != null) jedis.close();
}

3.3 Circuit Breaker

In high‑concurrency scenarios, add a circuit‑breaker (e.g., Netflix Hystrix) to protect the client.

3.4 Security

Configure strong passwords and enable SSL/TLS when possible (e.g., Alibaba Cloud Redis).

3.5 Memory Eviction Policies

Choose an appropriate maxmemory-policy based on workload. Default is volatile‑lru , which evicts LRU keys only among those with an expiration set. Other policies include:

allkeys‑lru : evict LRU keys regardless of TTL.

allkeys‑random : evict random keys.

volatile‑random : evict random expiring keys.

volatile‑ttl : evict keys closest to expiration.

noeviction : reject writes when memory is full.

4. Related Tools

4.1 Data Synchronization

Use redis‑port for cross‑instance data sync.

4.2 Big‑Key Search

Employ dedicated big‑key scanning utilities.

4.3 Hot‑Key Detection

Facebook’s redis‑faina (uses MONITOR ) can locate hot keys for short‑term analysis.

5. Appendix – Deleting Big Keys

5.1 Hash Deletion (hscan + hdel)

public void delBigHash(String host, int port, String password, String bigHashKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) jedis.auth(password);
    ScanParams params = new ScanParams().count(100);
    String cursor = "0";
    do {
        ScanResult
> result = jedis.hscan(bigHashKey, cursor, params);
        for (Entry
e : result.getResult()) {
            jedis.hdel(bigHashKey, e.getKey());
        }
        cursor = result.getStringCursor();
    } while (!"0".equals(cursor));
    jedis.del(bigHashKey);
}

5.2 List Deletion (ltrim)

public void delBigList(String host, int port, String password, String bigListKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) jedis.auth(password);
    long len = jedis.llen(bigListKey);
    int batch = 100;
    int removed = 0;
    while (removed < len) {
        jedis.ltrim(bigListKey, batch, len);
        removed += batch;
    }
    jedis.del(bigListKey);
}

5.3 Set Deletion (sscan + srem)

public void delBigSet(String host, int port, String password, String bigSetKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) jedis.auth(password);
    ScanParams params = new ScanParams().count(100);
    String cursor = "0";
    do {
        ScanResult
result = jedis.sscan(bigSetKey, cursor, params);
        for (String member : result.getResult()) {
            jedis.srem(bigSetKey, member);
        }
        cursor = result.getStringCursor();
    } while (!"0".equals(cursor));
    jedis.del(bigSetKey);
}

5.4 Sorted Set Deletion (zscan + zrem)

public void delBigZset(String host, int port, String password, String bigZsetKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) jedis.auth(password);
    ScanParams params = new ScanParams().count(100);
    String cursor = "0";
    do {
        ScanResult
result = jedis.zscan(bigZsetKey, cursor, params);
        for (Tuple t : result.getResult()) {
            jedis.zrem(bigZsetKey, t.getElement());
        }
        cursor = result.getStringCursor();
    } while (!"0".equals(cursor));
    jedis.del(bigZsetKey);
}

End of guide.

performanceCacheDatabaseredisbest practicesKey Design
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.