Last9 Last9

Mar 10th, ‘25 / 9 min read

Retrieving All Keys in Redis: Commands & Best Practices

Learn how to retrieve all keys in Redis efficiently. Explore key commands, performance tips, and best practices to avoid slowing down your database.

Retrieving All Keys in Redis: Commands & Best Practices

Need to list all the keys in your Redis database? If you're debugging an issue or just checking what's stored, retrieving all keys is a useful skill for any developer.

This guide covers everything you need to know—from the basic commands to the performance implications—so you can query Redis efficiently without slowing things down.

What is Redis and Why Do Keys Matter?

Redis is an in-memory data structure store used as a database, cache, message broker, and streaming engine. Think of it as your application's high-speed sidekick - blazing fast but with a different approach to data management than traditional databases.

Keys in Redis are the gateway to your data. Each piece of information stored in Redis has a key that you use to access it. Understanding how to work with these keys is essential for effective Redis management.

Basic Command to Get All Keys in Redis

The most straightforward way to get all keys in Redis is with the KEYS command:

KEYS *

That's it. This command returns all keys matching the pattern provided (in this case, the wildcard * matches everything).

Here's what it looks like in action:

127.0.0.1:6379> KEYS *
1) "user:1000"
2) "product:34891"
3) "session:abc123"
4) "counter:visits"

Simple enough, right? But before you start using this command everywhere, let's talk about why using KEYS it might not always be your best move.

💡
Monitoring Redis performance is just as important as querying it—check out this guide on Redis metrics to keep your database running smoothly.

Why You Shouldn't Use KEYS in Production

The KEYS command is easy to use, but it comes with a major catch - it's a blocking operation that scans the entire keyspace. In plain English: it can freeze your Redis server while it runs.

Here's why that's bad news:

  • In large databases, KEYS can take seconds or even minutes to complete
  • During this time, Redis stops processing other commands
  • Your application might time out waiting for responses
  • Users start wondering why your app suddenly feels like it's running on a 90s modem

This isn't just theoretical. I've seen production incidents triggered by a single KEYS command run during peak hours. Not a fun situation to explain to your boss.

A Better Way to Get All Redis Keys

The KEYS command is often used to fetch all keys in Redis, but it's not ideal for large datasets because it retrieves everything at once, potentially blocking the server.

A better approach is the SCAN command, which fetches keys incrementally.

Using SCAN Instead of KEYS

Example: Using SCAN

SCAN 0 MATCH * COUNT 100

This command:

  • Returns a batch of keys (default is 100, but Redis may adjust dynamically).
  • Provides a cursor value that helps paginate results.
  • Continues fetching keys until the cursor returns to 0.

Sample Execution in Redis CLI:

127.0.0.1:6379> SCAN 0 MATCH * COUNT 100
1) "163"
2) 1) "user:1000"
   2) "product:34891"

127.0.0.1:6379> SCAN 163 MATCH * COUNT 100
1) "0"
2) 1) "session:abc123"
   2) "counter:visits"

Since the second command returns a cursor of "0", we know we've retrieved all keys.

💡
If you're troubleshooting Redis or any other service, knowing how to check logs is essential—this guide on journalctl can help you track down issues.

How to Implement SCAN in Different Languages

Python Implementation

import redis

def get_all_keys(redis_client):
    keys = []
    cursor = 0
    while True:
        cursor, batch = redis_client.scan(cursor, match='*', count=100)
        keys.extend(batch)
        if cursor == 0:
            break
    return keys

# Usage
r = redis.Redis(host='localhost', port=6379)
all_keys = get_all_keys(r)
print(f"Found {len(all_keys)} keys")

Explanation:

  • Initializes an empty list to store keys.
  • Iterates through Redis using SCAN with a cursor.
  • Retrieves keys in batches of 100 and stops when the cursor returns to 0.

Node.js Implementation

const Redis = require('ioredis');

async function getAllKeys(redisClient) {
  const keys = [];
  let cursor = '0';
  
  do {
    const [nextCursor, batch] = await redisClient.scan(cursor, 'MATCH', '*', 'COUNT', 100);
    cursor = nextCursor;
    keys.push(...batch);
  } while (cursor !== '0');
  
  return keys;
}

// Usage
const redis = new Redis();
getAllKeys(redis).then(keys => {
  console.log(`Found ${keys.length} keys`);
});

Explanation:

  • Uses ioredis to interact with Redis.
  • Fetches keys in batches using SCAN.
  • Iterates through the results asynchronously until all keys are retrieved.
💡
For quick reference to useful commands while working with Redis or Linux in general, check out this Linux commands cheat sheet.

How to Filter Keys with Patterns

Often, you don't need all keys, just a subset matching a certain pattern. Redis supports wildcard matching:

  • * matches any sequence of characters.
  • ? matches any single character.
  • [abc] matches any single character inside the brackets.
  • [^abc] matches any single character NOT in the brackets.

Examples:

# Get all user-related keys
SCAN 0 MATCH user:* COUNT 100

# Get all session keys from a specific date
SCAN 0 MATCH session:2025-03-04:* COUNT 100

# Get all cache keys with numeric IDs
SCAN 0 MATCH cache:[0-9]* COUNT 100

How to Find Keys by Data Type

Sometimes, you need to filter keys based on their data type (e.g., string, list, set). While Redis doesn’t provide a direct command for this, we can use a combination of SCAN and TYPE.

Shell Script to Get Keys by Type:

# Get all keys and filter by type
redis-cli --scan --pattern '*' | while read key; do
  type=$(redis-cli type "$key")
  if [ "$type" = "string" ]; then
    echo "$key"
  fi
done

Explanation:

  • Scans for all keys.
  • Uses redis-cli type to check each key’s type.
  • Prints only keys that match a specified type (in this case, string).

This approach can be modified for other data types like list, hash, set, etc.

Performance Tips for Working with Keys in Large Redis Databases

When dealing with Redis at scale, these tips will help keep things running smoothly:

1. Schedule Key Operations During Low-Traffic Periods

If you need to run commands that operate on large numbers of keys, schedule them during off-peak hours when your system can better handle the load.

2. Use Key Naming Conventions

A good naming strategy makes key management easier:

service:entity:id:field

For example:

  • user:profile:1000:email
  • product:inventory:34891:count

This approach creates natural namespaces that you can easily filter with pattern matching.

3. Set Appropriate TTLs

Not all data needs to live forever. Setting expiration times (TTLs) on keys helps Redis automatically clean up stale data:

SET session:user:1000 "session_data" EX 3600  # expires in 1 hour

4. Monitor Your Keyspace Size

Keep an eye on your total key count with the INFO keyspace command:

127.0.0.1:6379> INFO keyspace
# Keyspace
db0:keys=1234,expires=632,avg_ttl=57983
💡
If you're dealing with memory issues in Redis, understanding OOM (Out of Memory) errors can be crucial—learn more about OOM here.

Redis Memory Optimization When Dealing with Many Keys

Each key in Redis consumes memory - not just for the value, but for the key itself and associated metadata. Here's how to keep memory usage in check:

Shorter Key Names Save Memory

While descriptive keys are nice, they consume memory. Consider:

# 49 bytes
user:profile:1000:preferences:theme:color

# 15 bytes
u:1000:p:t:c

In a database with millions of keys, this difference adds up quickly.

Instead of storing related data as separate keys:

user:1000:name "John"
user:1000:email "john@example.com"
user:1000:age 32

Use a hash to group them:

HSET user:1000 name "John" email "john@example.com" age 32

This dramatically reduces the number of keys and overall memory usage.

Practical Use Cases for Getting All Keys

Let's explore some common scenarios where you might need to retrieve all keys:

Data Migration Between Redis Instances

When moving data between Redis servers, you need to know what to transfer:

# Script outline for Redis migration
source_redis = redis.Redis(host='old-server', port=6379)
target_redis = redis.Redis(host='new-server', port=6379)

# Get all keys from source
keys = get_all_keys(source_redis)

# For each key, copy to target
for key in keys:
    # Get key type
    key_type = source_redis.type(key)
    
    # Handle different data types appropriately
    if key_type == b'string':
        target_redis.set(key, source_redis.get(key))
    elif key_type == b'hash':
        target_redis.hset(key, mapping=source_redis.hgetall(key))
    # Handle other types...

Explanation:

  • Connects to the source and target Redis servers.
  • Retrieves all keys from the source server.
  • Copies each key to the target server, handling different data types appropriately.

Debugging Cache Issues

When troubleshooting cache problems, examining keys can help identify patterns:

import redis
from collections import Counter

r = redis.Redis()
keys = get_all_keys(r)

# Analyze key prefixes
prefixes = [k.split(':')[0] for k in keys]
prefix_counts = Counter(prefixes)

print("Key namespace distribution:")
for prefix, count in prefix_counts.most_common():
    print(f"{prefix}: {count} keys")

Explanation:

  • Fetches all Redis keys and extracts their prefixes.
  • Counts occurrences of each prefix using Counter.
  • Prints a breakdown of key distributions to detect anomalies.
💡
Understanding log levels can help you better monitor Redis—this guide on log levels will clarify how to use them effectively.

Handling Redis Keys in a Cluster Environment

Redis Cluster distributes keys across multiple nodes, requiring a different approach to key retrieval.

from rediscluster import RedisCluster

def get_all_cluster_keys(cluster_client):
    all_keys = []
    
    # Get all master nodes
    nodes = [node for node in cluster_client.get_nodes() if not node.is_replica]
    
    # For each node, perform SCAN
    for node in nodes:
        node_client = node.redis_connection
        cursor = 0
        while True:
            cursor, keys = node_client.scan(cursor, match='*', count=100)
            all_keys.extend(keys)
            if cursor == 0:
                break
    
    return all_keys

# Usage
startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]
rc = RedisCluster(startup_nodes=startup_nodes)
keys = get_all_cluster_keys(rc)

Explanation:

  • Identifies master nodes in the Redis Cluster.
  • Iterates through each node, performing SCAN to fetch keys.
  • Aggregates keys from all master nodes to get a complete list.

Using the right approach for your Redis setup ensures efficient key retrieval without impacting performance.

Monitoring and Limiting Key Growth

Every Redis database needs boundaries. Here's how to monitor and control key growth:

Track Key Creation Rate

Set up monitoring to track the rate of key creation. A sudden spike could indicate an issue like missing TTLs or a runaway process.

Implement a Key Budget Per Service

Establish quotas for how many keys each service can create. This prevents one misbehaving service from crowding out others.

Understand Redis's maxmemory Policy

When Redis reaches its memory limit, its behavior depends on the maxmemory-policy setting:

# Check current policy
CONFIG GET maxmemory-policy

# Common settings:
# noeviction - Return errors when memory is full
# allkeys-lru - Evict least recently used keys
# volatile-lru - Evict least recently used keys with TTL

Choose a policy that matches your use case - generally volatile-lru provides a good balance.

💡
For better log management when working with Redis, understanding log retention is key—this article on log retention will guide you through it.

Redis Transactions When Operating on Multiple Keys

When you need to perform operations on multiple keys as a single atomic unit, use Redis transactions:

MULTI
GET user:1000:balance
GET user:1001:balance
SET user:1000:balance 400
SET user:1001:balance 600
EXEC

All commands between MULTI and EXEC are executed as a single atomic operation, ensuring data consistency.

A Quick Reference to Redis CLI Commands

Here's a quick reference for common Redis CLI commands related to keys:

Command Description Example
KEYS pattern Get all keys matching pattern (avoid in production) KEYS user:*
SCAN cursor [MATCH pattern] [COUNT count] Incrementally scan for keys SCAN 0 MATCH session:* COUNT 100
TYPE key Get the type of a key TYPE user:1000
TTL key Get remaining time to live of a key TTL session:abc123
EXPIRE key seconds Set a key's time to live in seconds EXPIRE cache:results 300
DEL key [key ...] Delete one or more keys DEL user:1000 user:1001
EXISTS key [key ...] Check if key(s) exist EXISTS login:token:xyz
RANDOMKEY Get a random key from the database RANDOMKEY
💡
Got questions about Redis keys or other Redis challenges? Join our Discord community to connect with other developers and share tips and tricks for optimizing your Redis usage.

FAQs

Can I safely use the KEYS command in my scripts?

No, the KEYS command should never be used in production environments or automated scripts. It's a blocking operation that scans the entire keyspace, which can cause performance issues and downtime. Always use SCAN for production use cases.

How can I count the total number of keys in Redis without retrieving them all?

You can use the DBSIZE command, which returns the number of keys in the current database without scanning the entire keyspace:

127.0.0.1:6379> DBSIZE
(integer) 1234

This command is much faster than KEYS or SCAN when you only need the count.

How do I find the biggest keys in my Redis database?

Redis doesn't have a built-in command to find the largest keys, but you can use the redis-cli tool with the --bigkeys option:

redis-cli --bigkeys

This scans your keyspace and reports the biggest keys of each data type, helping you identify memory hogs.

Is there a way to get all keys without pattern matching?

Yes, using SCAN with the default pattern (which is none) will return all keys:

SCAN 0 COUNT 100

This is equivalent to SCAN 0 MATCH * COUNT 100 but slightly more efficient since it doesn't perform pattern matching.

What happens if I delete a key while using SCAN?

SCAN provides a guarantee that every key present throughout a complete iteration will be returned at least once. If you delete keys during the scan, they won't be returned in later iterations. If you add keys during the scan, they may or may not be returned, depending on their hash values.

How do I get keys from a specific Redis database?

Redis supports multiple logical databases (numbered from 0 to 15 by default). To get keys from a specific database, you need to select that database first:

SELECT 2  # Switch to database 2
SCAN 0 MATCH * COUNT 100  # Now scanning database 2

Remember that each database has its own keyspace.

Can I get all keys with a specific TTL range?

Redis doesn't provide a direct way to query keys by TTL range. You'd need to:

  1. Get all keys with SCAN
  2. Check the TTL of each key with the TTL command
  3. Filter based on your criteria

Here's a simple Bash script that does this:

redis-cli --scan | while read key; do
  ttl=$(redis-cli ttl "$key")
  # Print keys that expire within an hour (TTL < 3600 and TTL > 0)
  if [ "$ttl" -lt 3600 ] && [ "$ttl" -gt 0 ]; then
    echo "$key expires in $ttl seconds"
  fi
done

Contents


Newsletter

Stay updated on the latest from Last9.

Authors
Anjali Udasi

Anjali Udasi

Helping to make the tech a little less intimidating. I love breaking down complex concepts into easy-to-understand terms.