funwithlinux blog

How to Show All Keys in Redis in One Line: Fixing the 'redis-cli keys *' Error

Redis, the popular in-memory data store, is widely used for caching, session management, and real-time analytics. A common task when working with Redis is listing all keys in a database—whether for debugging, data migration, or auditing. Many developers initially reach for the redis-cli keys * command, but this can lead to severe performance issues in production.

In this blog, we’ll explain why keys * is problematic, introduce the safer alternative (SCAN), and provide a step-by-step guide to listing all Redis keys efficiently. By the end, you’ll know how to avoid downtime and retrieve keys safely in one line (or a simple loop).

2026-01

Table of Contents#

  1. Understanding the 'redis-cli keys *' Command
  2. Why 'keys *' Is Problematic
    • 2.1 Blocking the Redis Event Loop
    • 2.2 Performance Impact on Large Datasets
    • 2.3 Scalability Issues
  3. The Better Alternative: The SCAN Command
    • 3.1 How SCAN Works
    • 3.2 Syntax and Key Options
  4. Step-by-Step Guide to Using SCAN
    • 4.1 Prerequisites: Verify redis-cli Installation
    • 4.2 Basic SCAN Usage
    • 4.3 Listing All Keys (Loop Until Cursor Reaches 0)
    • 4.4 Filtering Keys with MATCH
    • 4.5 Formatting Output
  5. Advanced Tips for SCAN
    • 5.1 Using SCAN with Patterns
    • 5.2 Counting Keys Safely
    • 5.3 Integrating SCAN into Scripts
  6. Common Errors and Fixes
  7. Conclusion
  8. References

Understanding the 'redis-cli keys *' Command#

The redis-cli keys * command is often the first solution developers find when searching for "how to list all Redis keys." At first glance, it seems straightforward:

redis-cli keys *  

This command returns all keys in the current Redis database that match the pattern * (i.e., all keys). For example, if your database has keys like user:100, session:abc, and config:default, keys * will list them all.

Example Output:#

1) "user:100"  
2) "session:abc"  
3) "config:default"  

Why 'keys *' Is Problematic#

While keys * works for small, development environments, it’s dangerous for production. Here’s why:

2.1 Blocking the Redis Event Loop#

Redis is single-threaded, meaning it processes one command at a time. The keys command scans the entire keyspace blocking all other operations until it completes. For a database with millions of keys, this can take seconds or even minutes—during which your application will experience timeouts or unavailability.

2.2 Performance Impact on Large Datasets#

The keys command has a time complexity of O(N), where N is the number of keys in the database. For 100,000 keys, it’s fast, but for 10 million keys, it becomes a bottleneck. This can trigger latency spikes, making keys unsuitable for production.

2.3 Scalability Issues#

As your Redis dataset grows, keys * becomes increasingly impractical. Cloud-hosted Redis services (e.g., AWS ElastiCache, Google Memorystore) often restrict or warn against using keys due to its impact on cluster stability.

The Better Alternative: The SCAN Command#

To safely list keys without blocking Redis, use the SCAN command. Introduced in Redis 2.8, SCAN is a non-blocking, cursor-based iterator that incrementally scans the keyspace.

3.1 How SCAN Works#

SCAN works by iterating over the keyspace in chunks:

  • Start with a cursor value of 0 (the initial scan).
  • Redis returns:
    • A new cursor (to use for the next iteration).
    • A subset of keys (up to a hinted count).
  • Repeat the process with the new cursor until the cursor returns to 0 (indicating the scan is complete).

This incremental approach ensures Redis can handle other commands between scans, avoiding blocking.

3.2 Syntax and Key Options#

The basic syntax for SCAN is:

redis-cli scan <cursor> [MATCH pattern] [COUNT count]  
  • <cursor>: The starting cursor (begin with 0).
  • MATCH pattern: Optional filter to return only keys matching a glob-style pattern (e.g., user:*).
  • COUNT count: Optional hint for how many keys to return per iteration (default: 10). Note: COUNT is not a guarantee—Redis may return more or fewer keys.

Step-by-Step Guide to Using SCAN#

Let’s walk through listing all keys safely with SCAN.

4.1 Prerequisites: Verify redis-cli Installation#

Ensure redis-cli is installed and accessible. Test with:

redis-cli --version  

If missing, install Redis (includes redis-cli) via your package manager (e.g., sudo apt install redis-server on Ubuntu).

4.2 Basic SCAN Usage#

Start with an initial scan using cursor 0:

redis-cli scan 0  

Example Output:

1) "123"  # Next cursor  
2) 1) "user:100"  
   2) "session:abc"  
   3) "config:default"  

Here, the cursor is 123, meaning we need to run SCAN again with 123 to continue.

4.3 Listing All Keys (Loop Until Cursor Reaches 0)#

To get all keys, loop until the cursor returns to 0. Use a bash loop for automation:

cursor=0  
while [ $cursor -ne 0 ]; do  
  # Run SCAN and capture output  
  result=$(redis-cli scan $cursor)  
  # Extract the new cursor (first value)  
  cursor=$(echo "$result" | head -n1 | awk '{print $1}')  
  # Extract and print keys (skip the cursor line)  
  echo "$result" | tail -n +2  
done  

How It Works:

  • The loop starts with cursor=0.
  • Each iteration runs SCAN, updates the cursor, and prints keys.
  • The loop exits when cursor becomes 0.

4.4 Filtering Keys with MATCH#

To list only keys matching a pattern (e.g., all user-related keys), use MATCH:

# List keys starting with "user:"  
redis-cli scan 0 MATCH user:*  

Example Output:

1) "456"  
2) 1) "user:100"  
   2) "user:101"  

4.5 Formatting Output#

Use redis-cli flags to format output for readability or scripting:

  • --raw: Output keys without Redis’s bulk reply formatting (e.g., no quotes or line numbers).

    redis-cli scan 0 MATCH user:* --raw  

    Output:

    456  
    user:100  
    user:101  
    
  • --csv: Output in CSV format (useful for parsing).

    redis-cli scan 0 MATCH user:* --csv  

    Output:

    "456","user:100","user:101"  
    
  • Save keys to a file:

    cursor=0  
    while [ $cursor -ne 0 ]; do  
      redis-cli scan $cursor --raw >> all_keys.txt  
      cursor=$(redis-cli scan $cursor --raw | head -n1)  
    done  

Advanced Tips for SCAN#

5.1 Using SCAN with Patterns#

Combine MATCH with wildcards to refine results:

  • *: Match any character sequence (e.g., user:*).
  • ?: Match a single character (e.g., user:10? matches user:100, user:101).
  • []: Match a range (e.g., user:[0-9] matches user:0 to user:9).

5.2 Counting Keys Safely#

To count keys without keys *, use:

  • DBSIZE: Returns the total number of keys (O(1) time, non-blocking).
    redis-cli dbsize  
  • SCAN + wc: Count keys matching a pattern (e.g., user:*):
    cursor=0  
    count=0  
    while [ $cursor -ne 0 ]; do  
      result=$(redis-cli scan $cursor MATCH user:* --raw)  
      cursor=$(echo "$result" | head -n1)  
      # Count keys (subtract 1 to exclude the cursor line)  
      keys_in_batch=$(echo "$result" | tail -n +2 | wc -l)  
      count=$((count + keys_in_batch))  
    done  
    echo "Total user keys: $count"  

5.3 Integrating SCAN into Scripts#

For automation, use SCAN in Python, Node.js, or other languages. Here’s a Python example with redis-py:

import redis  
 
r = redis.Redis(host='localhost', port=6379, db=0)  
cursor = 0  
all_keys = []  
 
while cursor != 0:  
    cursor, keys = r.scan(cursor=cursor, match='user:*', count=100)  
    all_keys.extend(keys)  
 
print(f"Found {len(all_keys)} user keys: {all_keys}")  

Common Errors and Fixes#

"NOAUTH Authentication required"#

Cause: Redis server requires a password.
Fix: Add the -a flag with your password:

redis-cli -a your_password scan 0  

Or authenticate after connecting:

redis-cli  
127.0.0.1:6379> AUTH your_password  
OK  
127.0.0.1:6379> scan 0  

"Could not connect to Redis at 127.0.0.1:6379: Connection refused"#

Cause: Redis server is not running, or the host/port is incorrect.
Fix:

  • Start Redis: sudo systemctl start redis-server.
  • Specify host/port explicitly:
    redis-cli -h redis-host -p 6380 scan 0  

Cursor Never Reaches 0#

Cause: SCAN may take multiple iterations for large datasets.
Fix: Be patient—continue looping until the cursor returns to 0.

Conclusion#

The keys * command is a quick fix but dangerous for production due to blocking and performance issues. The SCAN command provides a safe, non-blocking alternative by incrementally scanning the keyspace. By following the steps above, you can list all keys efficiently while keeping your Redis instance responsive.

Remember: Always test commands in staging before production, and use SCAN with MATCH and COUNT to tailor results to your needs.

References#