How to Use Redis SCAN Instead of KEYS for Safe Large‑Scale Key Enumeration
The article explains why the KEYS command can freeze a Redis instance with millions of keys, analyzes its O(n) blocking behavior, and demonstrates how the incremental SCAN command with cursor, MATCH, and COUNT parameters provides a non‑blocking alternative for retrieving prefixed keys.
When you need to inspect Redis keys that share a specific prefix, using the keys command can be dangerous, especially in production environments with large datasets.
Incident: In a production system where user tokens were stored with keys like user_token:userid , an operator ran keys user_token to count logged‑in users. Because the dataset contained millions of entries, the command blocked the single‑threaded Redis server, causing a near‑total outage.
Analysis: The KEYS command scans the entire keyspace with O(n) complexity; as the number of keys grows, execution time increases linearly, and Redis cannot process any other commands until it finishes.
Solution: Replace KEYS with the incremental SCAN command, which iterates over the keyspace in small steps using a cursor, avoiding thread blockage.
SCAN command format:
SCAN cursor [MATCH pattern] [COUNT count]The MATCH option filters keys by pattern, while COUNT hints at how many slots to examine per iteration (it is not a limit on returned results). The server does not keep state for the cursor; the client must supply the cursor returned by the previous call.
Important characteristics:
Complexity remains O(n) but work is split across calls, so the server stays responsive.
Provides pattern matching similar to KEYS .
May return duplicate keys; the client should deduplicate.
An empty result does not mean the scan is finished; the cursor must be zero to finish.
Example usage:
redis> scan 0 match user_token* count 5
1) "6"
2) 1) "user_token:1000"
2) "user_token:1001"
3) "user_token:1010"
4) "user_token:2300"
5) "user_token:1389"Starting from cursor 0 returns a new cursor (e.g., 6 ) and a batch of matching keys. Continue scanning with the returned cursor:
redis> scan 6 match user_token* count 5
1) "10"
2) 1) "user_token:3100"
2) "user_token:1201"
3) "user_token:1410"
4) "user_token:5300"
5) "user_token:3389"By iterating until the cursor returns to 0 , you can safely enumerate all matching keys without disrupting Redis performance.
Conclusion: Understanding the difference between KEYS and SCAN is a common interview topic and a practical skill for developers handling large Redis datasets; using SCAN prevents the server from becoming unresponsive.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.