Redis Commands
Commands grouped by data type with the complexity from the official reference and the gotcha that bites in production. Read the complexity column first: it tells you what is safe on a big key.
Complexity Is the Point
Redis runs commands on one thread, so one slow command delays every client. The Complexity column is copied from the command reference (redis.io/docs/latest/commands, data file commands.json in the redis/docs repository, checked 2026-10-31). N is almost always the size of the key or the number of items returned. Anything O(N) on a large key is a latency risk.
| Complexity | Meaning for you |
|---|---|
| O(1) | Safe at any size |
| O(log N) | Safe; sorted sets and similar |
| O(N) with N = items returned | Safe if you page (COUNT, LIMIT); dangerous when you ask for everything |
| O(N) with N = size of the key or keyspace | Avoid on big data in production (KEYS, SMEMBERS, HGETALL, LRANGE 0 -1) |
Strings, Counters, Key Management
Strings hold text, numbers or bytes (up to the string size limit in the docs). Counters use INCR.
| Command | What it does | Complexity | Gotcha |
|---|---|---|---|
SET k v [EX s | PX ms] [NX | XX] [GET] [KEEPTTL] | Set a value with optional expiry and conditions | O(1) | SET clears an existing TTL unless KEEPTTL; NX + EX is the basic lock primitive; GET option since 6.2 |
GET k | Read a string | O(1) | Returns nil for a missing key; WRONGTYPE error for other types |
SETNX, SETEX, PSETEX | Older set variants | O(1) | Marked deprecated in the command reference; use SET options |
MSET / MGET | Set / get many keys | O(N), N = number of keys | In Redis Cluster all keys must share one hash slot |
INCR / INCRBY / DECR | Atomic integer counter | O(1) | Value must be an integer string; creates the key at 0 if missing |
INCRBYFLOAT | Atomic float add | O(1) | Float rounding applies |
APPEND k v | Append to a string | O(1) amortised | Good for small appends |
GETDEL k | Read and delete atomically | O(1) | Since 6.2 |
GETEX k EX s | Read and change expiry | O(1) | Since 6.2; sliding-expiry cache pattern |
STRLEN / GETRANGE / SETRANGE | Length / substring / overwrite part | O(1) / O(N) returned / O(1) or O(M) copied | Offsets are in bytes |
EXISTS k [k ...] | Count how many keys exist | O(N), N = keys checked | Passing the same key twice counts twice |
DEL k [k ...] | Delete keys | O(N) keys; O(M) per big collection | Deleting a huge collection blocks the server |
UNLINK k [k ...] | Delete without blocking (memory freed in another thread) | O(1) per key | Since 4.0; prefer over DEL for big keys |
TYPE k | Data type of the key | O(1) | Returns none if missing |
RENAME a b | Rename a key | O(1) | Overwrites b; in Cluster both keys need the same slot |
COPY src dst | Copy a key | O(N) for collections | Since 6.2 |
SCAN cursor [MATCH p] [COUNT n] [TYPE t] | Iterate keys without blocking | O(1) per call, O(N) for a full pass | May return duplicates; a key present throughout is returned at least once; loop until the cursor is 0 |
KEYS pattern | List all matching keys | O(N) over the whole keyspace | Never in production; use SCAN |
OBJECT ENCODING k / OBJECT FREQ k | Internal encoding / access frequency (LFU policies) | O(1) | OBJECT FREQ needs an LFU maxmemory-policy |
MEMORY USAGE k | Bytes a key uses | O(N), N = samples | Since 4.0; includes overhead |
Hashes (objects) and Lists (queues)
Hashes model an object with fields. Lists are linked sequences, good at the two ends.
| Command | What it does | Complexity | Gotcha |
|---|---|---|---|
HSET k f v [f v ...] | Set one or more fields | O(1) per pair | Multiple pairs accepted since 4.0 (replaces HMSET) |
HGET k f, HMGET k f1 f2 | Read one / several fields | O(1) / O(N) fields | Missing field returns nil |
HGETALL k | All fields and values | O(N), N = hash size | Avoid on big hashes; use HSCAN |
HDEL k f, HLEN k, HKEYS k | Remove field, count, list names | O(N) removed / O(1) / O(N) | HKEYS is also O(N) of the whole hash |
HINCRBY k f n | Atomic counter in a field | O(1) | Per-object counters without read-modify-write |
HSCAN k cursor [MATCH p] [COUNT n] | Iterate fields | O(1) per call | Same duplicate caveat as SCAN |
HEXPIRE k seconds FIELDS n f ... | Expire individual hash fields | O(N), N = fields | Hash field expiration listed since 7.4.0 in the reference |
LPUSH / RPUSH k v ... | Add to head / tail | O(1) per element | Order of several values: LPUSH a b c leaves c first |
LPOP / RPOP k [count] | Remove from head / tail | O(N), N = elements returned | The count form needs 6.2+ |
LRANGE k start stop | Read a range | O(S+N) | LRANGE k 0 -1 returns everything: avoid on long lists |
LINDEX k i, LSET k i v | Read / write by index | O(N) to the index (O(1) at either end) | Middle access is slow on long lists |
LLEN k | Length | O(1) | |
LTRIM k start stop | Keep only a range | O(N) removed | LPUSH + LTRIM 0 99 = capped recent list |
LREM k count v | Remove matching values | O(N+M) | Scans the list |
LMOVE src dst LEFT RIGHT | Atomically move an element between lists | O(1) | Since 6.2; reliable-queue building block (replaces RPOPLPUSH) |
BLPOP k [k ...] timeout | Blocking pop | O(N) keys | Timeout 0 blocks forever; blocking commands hold the client connection |
Sets, Sorted Sets, Probabilistic Types
Sets: unique members. Sorted sets: unique members ordered by a score (leaderboards, delay queues, rate-limit windows).
| Command | What it does | Complexity | Gotcha |
|---|---|---|---|
SADD / SREM k m ... | Add / remove members | O(1) per add / O(N) removed | Returns the number actually added |
SISMEMBER k m, SMISMEMBER k m1 m2 | Membership test | O(1) / O(N) tested | SMISMEMBER since 6.2 |
SMEMBERS k | All members | O(N), N = set size | Use SSCAN for big sets |
SCARD k | Size | O(1) | |
SINTER / SUNION / SDIFF | Set algebra | O(N*M) worst case / O(N) / O(N) | Large sets block; ...STORE variants save the result |
SPOP / SRANDMEMBER k [count] | Remove / read random members | O(1) without count, O(N) with | |
ZADD k [NX|XX] [GT|LT] [CH] score m | Add or update a member's score | O(log N) per item | GT / LT since 6.2; CH counts changed members |
ZRANGE k start stop [BYSCORE|BYLEX] [REV] [LIMIT o c] [WITHSCORES] | Range by rank, score or lexicographic order | O(log N + M) | The unified form since 6.2; older ZRANGEBYSCORE and ZREVRANGE are deprecated in the reference |
ZRANK k m, ZSCORE k m | Rank / score of a member | O(log N) / O(1) | Rank is 0-based |
ZINCRBY k n m | Add to a score | O(log N) | Atomic leaderboard update |
ZCARD / ZCOUNT k min max | Size / count in a score range | O(1) / O(log N) | Use ( for exclusive bounds: (5 |
ZREM k m | Remove members | O(M log N) | |
ZPOPMIN / ZPOPMAX k [count] | Pop lowest / highest scores | O(log N * M) | Basis of a simple priority or delay queue |
ZREMRANGEBYRANK / ...BYSCORE | Trim a sorted set | O(log N + M) | Sliding-window rate limiting: remove old scores |
PFADD / PFCOUNT | HyperLogLog: approximate distinct count | O(1) | Fixed small memory; approximate by design |
SETBIT / GETBIT / BITCOUNT | Bit arrays | O(1) / O(1) / O(N) | Compact flags per user id |
GEOADD / GEOSEARCH | Geospatial index on a sorted set | O(log N) per item / O(N+log M) | Radius searches cost grows with results |
Streams, Pub/Sub, Transactions and Scripts
Streams are an append-only log with consumer groups (a lightweight Kafka-like model).
| Command | What it does | Complexity | Gotcha |
|---|---|---|---|
XADD s * f v [MAXLEN ~ n] | Append an entry (* = auto id) | O(1), O(N) when trimming | ~ trims approximately and is cheaper |
XLEN s, XRANGE s - + COUNT n | Length / read a range | O(1) / O(N) returned | Always pass COUNT |
XREAD COUNT n BLOCK ms STREAMS s id | Read new entries | See the reference (depends on streams) | $ means "only entries after now" |
XGROUP CREATE s g $ [MKSTREAM] | Create a consumer group | Depends on subcommand | Group needs an existing stream or MKSTREAM |
XREADGROUP GROUP g c COUNT n STREAMS s > | Read as a group member | O(M) returned | > means undelivered entries; an id such as 0 replays your pending ones |
XACK s g id | Acknowledge an entry | O(1) per id | Unacked entries stay in the pending list |
XPENDING s g | Inspect unacknowledged entries | O(N) returned | Find stuck consumers |
XAUTOCLAIM s g c min-idle 0 | Take over idle pending entries | O(1) with small COUNT | Reply gained an element in 7.0 |
XTRIM / XDEL | Trim by length or id / delete entries | O(N) evicted / O(1) each | XDEL removes entries by id; use XTRIM to bound stream size |
PUBLISH ch msg, SUBSCRIBE ch | Fire-and-forget messaging | O(N+M) / O(N) | Subscribers that are offline miss messages; use streams for durability |
SPUBLISH / SSUBSCRIBE | Sharded pub/sub for Cluster | O(N) subscribers | Since 7.0 |
MULTI ... EXEC | Queue commands and run them as one atomic block | Depends on commands | No rollback: a command that errors at run time does not undo the others |
WATCH k ... MULTI ... EXEC | Optimistic locking | O(1) per key | If a watched key changes, EXEC returns nil: retry |
EVAL script numkeys k ... arg ..., EVALSHA | Run a Lua script atomically | Depends on the script | Declare keys in KEYS, not in the script text; long scripts block |
FUNCTION LOAD, FCALL | Redis Functions (server-side libraries) | O(1) load, depends on function | Since 7.0; persisted with the dataset |
Expiry and Memory Limits
Expiry removes keys by time; eviction removes keys when memory is full. Different mechanisms.
| Command | What it does | Complexity | Gotcha |
|---|---|---|---|
EXPIRE k s [NX|XX|GT|LT] | Set a TTL in seconds | O(1) | Options since 7.0; PEXPIRE for milliseconds, EXPIREAT for a Unix time |
TTL k / PTTL k | Remaining time | O(1) | -1 = no expiry, -2 = key does not exist |
PERSIST k | Remove the TTL | O(1) | |
EXPIRETIME k | Absolute expiry time | O(1) | Since 7.0 |
| Overwriting a key | SET removes the TTL; INCR, LPUSH and similar keep it | n/a | Re-apply the TTL after rewrites |
CONFIG SET maxmemory 2gb | Memory limit | O(N) parameters | Without a limit Redis can grow until the OS kills it |
maxmemory-policy noeviction | Writes fail with an error when full | n/a | Default policy per the eviction docs |
allkeys-lru / allkeys-lfu / allkeys-random | Evict any key by recency / frequency / randomly | n/a | The docs call allkeys-lru a good default when you have no other preference; LRU is approximate (sampling) |
volatile-lru / volatile-lfu / volatile-random / volatile-ttl | Evict only keys that have a TTL | n/a | With no TTL keys they behave like noeviction |
allkeys-lrm / volatile-lrm | Least recently modified policies | n/a | Listed in the current docs; not in older releases, check your version |
INFO memory, INFO stats | used_memory, evicted_keys, expired_keys | O(1) | Rising evicted_keys means the cache is too small |
RDB, AOF, Replicas
Persistence choices checked against the Redis persistence documentation.
| Item | What it does | Complexity | Gotcha |
|---|---|---|---|
RDB (save <seconds> <changes>) | Periodic point-in-time snapshot to dump.rdb | n/a | You can lose writes since the last snapshot |
BGSAVE | Snapshot in a child process | O(1) to start | Fork can pause the main thread on very large datasets; SAVE blocks and is O(N) |
LASTSAVE | Time of the last successful save | O(1) | Use it to confirm snapshots happen |
AOF (appendonly yes) | Log of every write, replayed on start | n/a | Since 7.0 AOF is split into several files in the appenddirname directory |
appendfsync everysec | Fsync once per second (the suggested default) | n/a | You can lose about one second of writes |
appendfsync always | Fsync on every write batch | n/a | Safest and slowest |
appendfsync no | Let the OS flush | n/a | Fastest, least safe |
BGREWRITEAOF | Compact the AOF in the background | O(1) to start | Rewrite uses disk and memory while running |
WAIT n timeout, WAITAOF | Block until replicas or local AOF acknowledge the writes | O(1) | WAITAOF since 7.2; acknowledgement still is not a full consensus guarantee |
REPLICAOF host port / REPLICAOF NO ONE | Make this node a replica / promote it | O(1) | Old name SLAVEOF |
ROLE, INFO replication | Show role, offsets, lag | O(1) | Compare master_repl_offset with replica offsets |
FAILOVER | Coordinated switchover to a replica | O(1) | Since 6.2 |
Cluster, Diagnostics, Admin
Cluster spreads keys over 16384 hash slots (stated in the cluster documentation); a key's slot is a hash of its name, and {tag} parts force related keys into one slot.
| Command | What it does | Complexity | Gotcha |
|---|---|---|---|
CLUSTER INFO | Cluster state, slots assigned, known nodes | O(1) | cluster_state:ok is what you want |
CLUSTER NODES | All nodes with ids, roles, slot ranges, flags | O(N) nodes | fail and handshake flags show trouble |
CLUSTER SHARDS | Shard-oriented view (since 7.0) | O(N) nodes | Replaces CLUSTER SLOTS, which is deprecated in the reference |
CLUSTER KEYSLOT key | Which slot a key maps to | O(N) bytes in key | Check hash-tag usage |
CLUSTER COUNTKEYSINSLOT slot | Keys in a slot | O(1) | Useful during resharding |
CLUSTER MEET ip port | Introduce a node | O(1) | Usually done by redis-cli --cluster |
CLUSTER FAILOVER | Manual replica takeover (run on the replica) | O(1) | Safer than killing the master |
MOVED / ASK errors | Key lives on another node / slot is migrating | n/a | Use a cluster-aware client or redis-cli -c |
INFO [section] | Server metrics | O(1) | Sections: server, clients, memory, persistence, stats, replication, cpu, keyspace |
DBSIZE | Number of keys in the selected database | O(1) | |
SLOWLOG GET 10 | Recent slow commands | O(N) returned | Threshold set by slowlog-log-slower-than |
LATENCY DOCTOR | Human-readable latency report | O(1) | Needs the latency monitor threshold configured |
MEMORY DOCTOR | Memory problem hints | O(1) | |
CLIENT LIST / CLIENT KILL | List / disconnect clients | O(N) clients | Look for idle or blocked clients |
MONITOR | Stream every command received | n/a | Heavy; reduces throughput, never leave it running; also exposes data |
CONFIG GET / CONFIG SET / CONFIG REWRITE | Read, change, persist configuration | O(N) params / O(1) | CONFIG SET is lost on restart unless rewritten |
FLUSHDB / FLUSHALL [ASYNC] | Delete all keys in one DB / all DBs | O(N) | No undo; many deployments restrict it with ACLs |
ACL SETUSER, AUTH, HELLO | Users, authentication, protocol negotiation | O(N) rules / O(N) passwords / O(1) | HELLO 3 switches to RESP3 |
SHUTDOWN [NOSAVE|SAVE] | Stop the server | O(N) when saving | Default saves if persistence is on |
redis-cli Options
Option names checked against redis-cli.c in the Redis source (unstable branch); redis-cli --help shows your build's list.
| Option | What it does | Gotcha |
|---|---|---|
-h host -p port | Connect to a host and port | Defaults to 127.0.0.1:6379 |
-u redis://user:pass@host:6379/0 | Connect with a URI | Passwords on the command line show in the process list |
-a password / --user name --pass pw / --askpass | Authenticate | --askpass prompts so nothing is left in history |
-n 2 | Select a database | Cluster mode has database 0 only |
-c | Follow MOVED and ASK redirects | Needed for Cluster |
--tls, --insecure | Use TLS; skip certificate verification | --insecure only for tests |
-3 | Use RESP3 | Output format changes |
--raw / --no-raw | Raw or formatted output | Raw is the default when output is not a terminal |
--csv, --json | Machine-readable output | Handy for scripts |
-x | Read the last argument from stdin | For setting binary or multi-line values |
-r 10 -i 1 cmd | Repeat a command 10 times, 1 second apart | -r -1 repeats forever |
--scan --pattern "user:*" [--count n] | Iterate keys with SCAN | Safe alternative to KEYS |
--bigkeys, --memkeys, --keystats | Sample the keyspace for the largest keys / memory use / statistics | Uses SCAN; --memkeys and --keystats exist in newer builds |
--hotkeys | Find hot keys | Works only with an LFU eviction policy |
--latency, --latency-history, --latency-dist | Measure latency (live, over time, as a distribution) | Measures from the client, includes the network |
--intrinsic-latency 5 | Measure system latency on the machine running it | Run on the Redis host, not remotely |
--stat | Rolling server statistics | A quick top for Redis |
--rdb file | Download an RDB snapshot from the server | Triggers a save on the server |
--pipe | Mass insert from a stream of protocol text | Much faster than one command per line |
--cluster create|check|reshard ... | Cluster administration | Manage with care; --cluster-yes auto-confirms |
--eval script.lua keys , args | Run a Lua script file | A comma separates keys from arguments |
Redis Mistakes
- **
KEYS *in production.** O(N) over the keyspace, blocks everyone. UseSCAN. - **
HGETALL,SMEMBERS,LRANGE 0 -1on big keys.** Page withHSCAN,SSCAN, ranges. - **Caching without a TTL and without
maxmemory.** The instance grows until it is killed. Set both. - **Assuming
SETkeeps the TTL.** It clears it unless you passKEEPTTL. - Using pub/sub where messages must not be lost. Offline subscribers miss them; use Streams.
- **Treating
MULTI/EXEClike a database transaction.** There is no rollback. - Multi-key commands across slots in Cluster. Use hash tags like
{user:1}:cart. - **Big deletes with
DEL.** UseUNLINK. - **
MONITORleft running.** It slows the server and leaks data. - **One lock key with
SETNXand no expiry.** A crashed holder blocks everyone forever; useSET k v NX EX 30and a unique value.
Long-form pages and what was checked
| Topic | Page |
|---|---|
| Redis data model, persistence and clustering in depth | Redis |
| Caching strategies and invalidation | Caching Patterns |
| Choosing a database | NoSQL Fundamentals |
| Redis as a Spring cache | Caching & Resilience |
| Cache performance | Performance: Caching |
Checked on 2026-10-31: every complexity string and "since" version in this sheet against the machine-readable command reference (commands.json in the redis/docs repository, which backs redis.io/docs/latest/commands); deprecation marks for SETNX, SETEX, ZRANGEBYSCORE, ZREVRANGE and CLUSTER SLOTS from the same file; eviction policies and the noeviction policy from the Redis eviction documentation (the current docs also list the lrm policies, which are newer); persistence behaviour (RDB, appendfsync modes, multi-part AOF since 7.0) from the persistence documentation; redis-cli option names from redis-cli.c (unstable). No Redis server was available locally, so no command was executed. The 16384-slot figure and the hash-tag rule are standard Redis Cluster facts not re-fetched for this sheet.