Connecting
Default port is 6379. Build a URL for your host with the Redis connection string generator.
| Command | What it does |
|---|---|
| Connect to localhost on port 6379 | |
| Connect to a remote host and port | |
| Log in as an ACL user, prompt for the password | |
| Connect with a URL, database number at the end | |
| Same over TLS (note the double s) | |
| TLS with your own CA certificate | |
| Pass the password without it showing in | |
| Silence the password-on-command-line warning | |
| Cluster mode, follows MOVED redirects for you | |
| Connect straight to database 2 | |
| Log in from inside an open session | |
| Switch to database 2 (0-15 by default) | |
| Returns PONG when the server is reachable | |
| Run one command and exit, handy in scripts |
Example: connect over TLS to database 1 without leaving the password in your shell history.
export REDISCLI_AUTH='s3cret'
redis-cli -u rediss://[email protected]:6380/1 PING # PONG over TLS
redis-cli -u rediss://[email protected]:6380/1
Keys
Use SCAN to list keys. KEYS walks the whole keyspace in one blocking call. Turn seconds into readable TTLs with the Redis TTL converter.
| Command | What it does |
|---|---|
| Iterate keys matching a pattern without blocking | |
| Iterate only keys of one type | |
| Print every matching key, SCAN under the hood | |
| DestructiveBlocks the server until every key is checked | |
| Count keys in the current database | |
| 1 if the key exists, 0 if not | |
| Data type: string, hash, list, set, zset, stream | |
| Delete keys, freeing memory in the foreground | |
| Delete a key and free its memory in the background | |
| Rename a key, overwriting the target | |
| Copy a key to a new name | |
| Delete the key after 3600 seconds | |
| Set a TTL only if the key has none | |
| Seconds left; -1 means no TTL, -2 means no key | |
| Unix time when the key expires | |
| Remove the TTL so the key never expires | |
| DestructiveDelete every key matching a pattern | |
| DestructiveDelete every key in the current database | |
| DestructiveDelete every key in every database | |
| DestructiveSame, freeing memory in the background |
In 1bench: the Redis GUI shows keys as a namespace tree with types and TTLs, loaded with SCAN, so you can find a key without typing KEYS * against production.
Example: count the session keys, then list the ones that have no TTL.
redis-cli --scan --pattern 'session:*' | wc -l # how many sessions exist
redis-cli --scan --pattern 'session:*' | while read -r k; do # which never expire
[ "$(redis-cli TTL "$k")" = "-1" ] && echo "$k"
done
Strings
| Command | What it does |
|---|---|
| Store a value, quotes for spaces | |
| Store with a 30 minute TTL | |
| Set only if missing, 30s TTL; a simple lock | |
| Overwrite the value but keep the existing TTL | |
| Read a value, nil if missing | |
| Set several keys in one call | |
| Read several keys in one call | |
| Read and reset the TTL in one step | |
| Read and delete in one step | |
| Add 1 atomically, creates the key at 0 | |
| Add any integer atomically | |
| Add a decimal atomically | |
| Subtract 1 atomically | |
| Length of the value in bytes |
Example: a per-minute rate limit for user 1001, built from and .
redis-cli INCR rate:1001:202610121405 # (integer) 1, reject above 100
redis-cli EXPIRE rate:1001:202610121405 60 NX # window closes after a minute
Hashes
| Command | What it does |
|---|---|
| Set one or more fields | |
| Read one field | |
| Read several fields | |
| Read every field and value | |
| List field names only | |
| Count fields | |
| 1 if the field exists | |
| Remove a field | |
| Add to a numeric field atomically | |
| Set a field only if it is missing | |
| Iterate fields of a large hash | |
| Expire one field after 300 seconds | |
| Seconds left on a field's TTL | |
| Set a field and its TTL together (Redis 8+) |
still works but is deprecated. takes multiple pairs.
In 1bench: the Redis GUI lets you edit several hash, list, set or sorted set fields and save them together. Each write checks the key has not changed since you loaded it and keeps its TTL.
Example: store a user profile as a hash, bump its login count and read three fields back.
redis-cli HSET user:1001 name "Ada Lovelace" email [email protected] plan pro logins 0
redis-cli HINCRBY user:1001 logins 1
redis-cli HMGET user:1001 name plan logins # "Ada Lovelace", "pro", "1"
Sorted Sets
Since Redis 6.2, covers what and did. The old commands still run.
| Command | What it does |
|---|---|
| Add a member with a score, or update it | |
| Update only if the new score is higher | |
| Add to a member's score | |
| Read one member's score | |
| Position from the lowest score, 0-based | |
| Top 10 by score, highest first | |
| Members with scores between 1000 and 2000 | |
| Scores above 1000, first 20 | |
| Older form of the top 10 query | |
| Count members | |
| Count members in a score range | |
| Remove a member | |
| Remove members with scores up to a cutoff | |
| Iterate members of a large set |
Example: a weekly leaderboard that adds points for two users and reads back the top three.
redis-cli ZINCRBY leaderboard:2026-w41 120 user:1001
redis-cli ZINCRBY leaderboard:2026-w41 95 user:1002
redis-cli ZRANGE leaderboard:2026-w41 0 2 REV WITHSCORES # user:1001 120, user:1002 95
Streams
An append-only log with consumer groups. Entry IDs look like ; lets Redis pick one.
| Command | What it does |
|---|---|
| Append an entry, returns its ID | |
| Append and cap the stream near 100k entries | |
| Count entries | |
| Oldest 10 entries | |
| The newest entry | |
| Wait up to 5s for new entries | |
| Create a consumer group, and the stream if missing | |
| Read entries not yet given to this group | |
| Mark an entry as processed | |
| Summary of delivered but unacked entries | |
| Pending entries for one consumer | |
| Take over entries idle for more than 60s | |
| Groups, consumers, lag and last delivered ID | |
| DestructiveDrop the oldest entries beyond 100k | |
| DestructiveDrop entries older than an ID | |
| Delete one entry by ID |
Example: create a billing consumer group, add an order, read it as worker-1 and acknowledge it.
redis-cli XGROUP CREATE orders billing $ MKSTREAM
redis-cli XADD orders '*' order_id 42 user 1001 total 49.90
redis-cli XREADGROUP GROUP billing worker-1 COUNT 1 STREAMS orders '>' # returns ID 1760270400000-0
redis-cli XACK orders billing 1760270400000-0
Lists and Sets
| Command | What it does |
|---|---|
| Push to the head of a list | |
| Push to the tail | |
| Take from the head | |
| Take up to 5 from the tail | |
| Wait up to 5s for an item, 0 waits forever | |
| Move an item between lists atomically | |
| Same, waiting up to 5s for an item | |
| Read the whole list | |
| Count items | |
| Remove one matching item | |
| Keep only the first 100 items | |
| Add members to a set | |
| Read every member | |
| 1 if the member is in the set | |
| Count members | |
| Remove a member | |
| Members in both sets |
Example: a job queue that parks each job on a processing list until the worker removes it.
redis-cli RPUSH jobs '{"id":7,"type":"invoice","order":42}'
redis-cli BLMOVE jobs jobs:processing LEFT RIGHT 5 # held here until the worker finishes
redis-cli LREM jobs:processing 1 '{"id":7,"type":"invoice","order":42}'
Pub/Sub
Messages go only to clients subscribed at that moment. Nothing is stored; use a stream when you need history.
| Command | What it does |
|---|---|
| Send a message, returns how many clients got it | |
| Listen on a channel until you quit | |
| Listen on every channel matching a pattern | |
| Stop listening on a channel | |
| Channels with at least one subscriber | |
| Subscriber count for a channel | |
| Sharded publish, stays on one cluster shard | |
| Emit an event whenever a key expires | |
| Receive those expiry events for database 0 |
Example: watch expiry events in one terminal while a 5-second session key expires in another.
redis-cli CONFIG SET notify-keyspace-events Ex
redis-cli PSUBSCRIBE '__keyevent@0__:expired' # terminal 1: watch expiries
redis-cli SET session:abc 1001 EX 5 # terminal 2: fires in 5 seconds
Transactions and Lua
| Command | What it does |
|---|---|
| Start queuing commands | |
| Run the queued commands as one block | |
| Throw away the queue | |
| Make the next EXEC fail if this key changes | |
| Stop watching all keys | |
| Run a Lua script atomically | |
| Cache a script, returns its SHA1 | |
| Run a cached script by hash | |
| Run a script file; keys before the comma, args after | |
| Load a function library (Redis 7+) | |
| Call a loaded function |
Example: take a lock with , then release it with Lua only if this worker still holds it.
cat > release.lua <<'EOF' # delete the lock only if this worker holds it
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
end
return 0
EOF
redis-cli SET lock:order:42 worker-1 NX PX 30000
redis-cli --eval release.lua lock:order:42 , worker-1 # (integer) 1, lock released
JSON
JSON commands are built into Redis 8. On Redis 7 they need the RedisJSON module (Redis Stack). Shell quoting gets messy with nested JSON; the Redis escape tool helps.
| Command | What it does |
|---|---|
| Store a JSON document | |
| Read the whole document | |
| Read one path | |
| Update one path; strings need inner quotes | |
| Read one path from several keys | |
| Add to a number in place | |
| Append to an array | |
| Remove a path | |
| Type at a path |
Example: store a preferences document, append a language to its array and read the array back.
redis-cli JSON.SET user:1001:prefs '$' '{"theme":"dark","langs":["en"],"visits":0}'
redis-cli JSON.ARRAPPEND user:1001:prefs '$.langs' '"de"'
redis-cli JSON.GET user:1001:prefs '$.langs' # [["en","de"]]
Server and Monitoring
Estimate memory before you load data with the Redis memory calculator.
| Command | What it does |
|---|---|
| Every server stat, grouped into sections | |
| Version, mode, uptime and config file path | |
| Used memory, peak, fragmentation ratio | |
| Key and expiring key counts per database | |
| Bytes one key uses | |
| Find the largest key of each type, via SCAN | |
| Find the keys using the most memory | |
| Rolling stats line every second | |
| Measure round-trip latency to the server | |
| The 10 most recent slow commands | |
| Every connected client and what it is doing | |
| Stream every command the server runs; costly on busy servers | |
| Current eviction policy | |
| Evict least recently used keys at the memory limit | |
| Save runtime CONFIG SET changes to redis.conf | |
| Write an RDB snapshot in a background process | |
| DestructiveSnapshot in the foreground, blocks every client | |
| Installed server version |
In 1bench: the Redis GUI lays out INFO as a dashboard with memory, ops/sec, hit rate, evictions and per-database key counts.
Example: check memory use, fragmentation and eviction policy, then find the keys using the most memory.
redis-cli INFO memory | grep -E 'used_memory_human|maxmemory_human|mem_fragmentation_ratio'
redis-cli CONFIG GET maxmemory-policy
redis-cli --memkeys
Valkey and Dragonfly
Valkey is a fork of Redis 7.2.4, so every command above works and takes the same flags as . Dragonfly speaks the Redis protocol on port 6379 and works with ; these rows differ.
| Command | What it does |
|---|---|
| Valkey's client, same flags as redis-cli | |
| Start Dragonfly with a password on the default user | |
| Evict keys near the memory limit, like a cache | |
| Answer CLUSTER commands as a single node | |
| Write a snapshot every hour | |
| Write snapshots as Redis RDB instead of Dragonfly's format | |
| Dragonfly's HSETEX: seconds first, no FIELDS keyword | |
| Seconds left on one hash field (Dragonfly) |
Example: run Dragonfly in Docker as a password-protected cache and ping it with .
docker run -d -p 6379:6379 --ulimit memlock=-1 \
docker.dragonflydb.io/dragonflydb/dragonfly --requirepass s3cret --cache_mode=true
REDISCLI_AUTH=s3cret redis-cli PING
Gotchas
- runs on the single command thread and checks every key before it returns, so on a large database every other client waits. Use or . can return a key twice and is a hint, not a page size.
- wipes every database on the server, not only the one you selected, and there is no undo. Protect production with an ACL rule such as for app users.
- on a hash or list with millions of items blocks while it frees memory. returns at once and frees in the background.
- A plain on an existing key removes its TTL. Add , or set the TTL again in the same call with .
- In a cluster, multi-key commands such as , blocks and Lua scripts fail with CROSSSLOT unless every key hashes to the same slot. Put the shared part in braces: and .
- and passwords in URLs end up in shell history and process lists. Use or the environment variable.