Redis Cheatsheet

redis-cli and Debugging

Use this Redis reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Connecting

redis-cli                                  # 127.0.0.1:6379
redis-cli -h cache.example.com -p 6380
redis-cli -h host -p 6379 -a "$REDIS_PASSWORD" -n 3      # -n selects the database
redis-cli -u 'redis://user:pass@host:6379/0'             # URI form
redis-cli -u 'rediss://user:pass@host:6380/0' --tls      # TLS
redis-cli --tls --cacert ca.crt --cert client.crt --key client.key -h host -p 6380
redis-cli -c -h host                                     # follow Cluster redirects
redis-cli -3                                             # negotiate RESP3 (HELLO 3)
FlagMeaning
-h -pHost and port
-a passPassword, warns that it is visible in ps
--user nameACL username (6.0+)
--pass passSame as -a, no warning
--askpassPrompt instead, the safe form for a shell
-n dbDatabase number
-u uriredis:// or rediss://
--tlsTLS, with --cacert, --cert, --key, --sni
-cFollow MOVED and ASK in Cluster
-3 / -2Force RESP3 or RESP2
-r n -i sRepeat a command n times, every s seconds
-t sConnection timeout

Prefer REDISCLI_AUTH or --askpass over -a, since a password on the command line lands in ps output and shell history.

Output modes and scripting

redis-cli --raw GET hu:k              # no quoting, no type prefixes, UTF-8 through
redis-cli --no-raw LRANGE hu:l 0 -1   # force the pretty numbered form in a pipe
redis-cli --json GET hu:json          # JSON output
redis-cli -x SET hu:blob < photo.bin  # last argument from stdin
redis-cli --quoted-input SET k "a\x00b"    # accept escapes in the input
redis-cli -r 5 -i 1 INFO clients | grep connected_clients
redis-cli --eval script.lua key1 key2 , arg1 arg2   # note the SPACED comma

Three things that bite in scripts:

- Output is raw when stdout is not a tty and formatted when it is, so the same command prints differently in a pipe. Pin it with --raw or --no-raw. - --eval separates keys from args with a comma that must have spaces around it. numkeys is inferred from how many precede it. - -r -1 repeats forever, which with -i makes a poor man's monitoring loop.

Scanning and finding big keys

redis-cli --scan                                  # every key, safely, via SCAN
redis-cli --scan --pattern 'hu:session:*'
redis-cli --scan --pattern 'hu:tmp:*' --count 1000 | xargs -L 100 redis-cli UNLINK

redis-cli --bigkeys        # biggest key per type, by element count
redis-cli --memkeys        # biggest key per type, by MEMORY USAGE bytes
redis-cli --keystats       # both at once, plus a size distribution
redis-cli --hotkeys        # most accessed keys, REQUIRES an LFU maxmemory-policy
redis-cli --bigkeys --pattern 'hu:*'
ToolAnswersCost
--bigkeysWhich key has the most elements, per typeFull SCAN, one *LEN per key
--memkeysWhich key uses the most bytesFull SCAN, one MEMORY USAGE per key
--keystatsBoth, with a distribution histogramBoth of the above
--hotkeysWhich keys are accessed mostFull SCAN plus OBJECT FREQ

All of them do a complete SCAN, so they are safe to run against production but they do take time and add load proportional to your keyspace. --hotkeys errors out unless maxmemory-policy is allkeys-lfu or volatile-lfu, because it reads OBJECT FREQ.

Never use KEYS * for any of this. --scan exists precisely so you do not have to.

Latency

redis-cli --latency                  # min, max, avg over a rolling window
redis-cli --latency-history -i 5     # a new sample line every 5 seconds
redis-cli --latency-dist             # a spectrum, needs a 256-color terminal
redis-cli --latency-percentiles      # p50, p99, p99.9
redis-cli --intrinsic-latency 10     # measures the KERNEL, not Redis

--latency measures round-trip PING time from where you run it, so it includes your network. --intrinsic-latency runs a tight busy loop and reports the worst scheduling delay the host kernel imposed, with no Redis involved. Run it on the Redis box itself: if it reports 5ms, no amount of Redis tuning will get you below that, and you have a noisy neighbour or a transparent-hugepage problem.

The server-side latency monitor is separate and off by default.

redis-cli CONFIG SET latency-monitor-threshold 100    # record events over 100ms
redis-cli LATENCY LATEST      # event, last time, last value, max value
redis-cli LATENCY HISTORY command
redis-cli LATENCY RESET
redis-cli LATENCY DOCTOR      # prose analysis of what it recorded
redis-cli MEMORY DOCTOR       # prose analysis of memory

LATENCY DOCTOR and MEMORY DOCTOR return human-readable advice, and both cheerfully tell you they have nothing to say on a healthy or idle instance.

Slow queries

redis-cli CONFIG SET slowlog-log-slower-than 10000   # microseconds, 10000 = 10ms
redis-cli CONFIG SET slowlog-max-len 256
redis-cli SLOWLOG GET 10
redis-cli SLOWLOG LEN
redis-cli SLOWLOG RESET
redis-cli SLOWLOG HELP
1) 1) (integer) 14                     <- entry id
   2) (integer) 1789531888             <- unix timestamp
   3) (integer) 42311                  <- microseconds of EXECUTION time
   4) 1) "HGETALL"                     <- the command and its args, truncated
      2) "hu:user:1042"
   5) "127.0.0.1:61083"                <- client address
   6) ""                               <- client name, from CLIENT SETNAME

The duration is execution time only. It excludes time spent on the network and time the command waited in the queue behind something else, so a client seeing 200ms while the slowlog says 0.4ms means the delay is elsewhere: a slow neighbour command, a fork pause, or the network. slowlog-log-slower-than 0 logs everything and -1 disables logging.

MONITOR

redis-cli MONITOR
# 1789531888.747123 [0 127.0.0.1:61083] "HGETALL" "hu:user:1042"
redis-cli MONITOR | grep -i flushall            # what you are usually looking for
redis-cli MONITOR | head -1000 > /tmp/trace.txt

MONITOR streams every command from every client to your connection. The documented cost is a large throughput hit, roughly 50 percent or worse on a busy server, and it can saturate your network link on its own. Use it for seconds at a time on production, never leave it attached, and never pipe it into something slow, because a slow MONITOR consumer fills its output buffer and gets disconnected.

It also shows plaintext arguments, so it leaks whatever your keys and values contain. The lower-cost alternatives are INFO commandstats for aggregate command counts and SLOWLOG for the outliers.

INFO

redis-cli INFO                    # every default section
redis-cli INFO memory
redis-cli INFO replication clients        # several sections, 7.0+
redis-cli INFO commandstats
redis-cli INFO latencystats               # 7.0+
redis-cli INFO everything                 # including the expensive sections
redis-cli CONFIG RESETSTAT                # zero the counters
SectionWatch
serverredis_version, uptime_in_seconds, config_file
clientsconnected_clients, blocked_clients, client_recent_max_output_buffer
memoryused_memory_human, used_memory_rss, mem_fragmentation_ratio, maxmemory_policy
persistencerdb_last_bgsave_status, aof_last_write_status, loading
statsinstantaneous_ops_per_sec, keyspace_hits/misses, evicted_keys, expired_keys, rejected_connections
replicationrole, master_link_status, master_repl_offset, slave_repl_offset
cpuused_cpu_sys, used_cpu_user
commandstatscmdstat_<cmd>:calls, usec, usec_per_call, rejected_calls, failed_calls
latencystatsPer-command p50, p99, p99.9 (7.0+)
errorstatsCounts per error reply type (6.2+)
keyspacedb0:keys=...,expires=...,avg_ttl=...
# Cache hit rate
redis-cli INFO stats | grep -E 'keyspace_(hits|misses)'

# The three numbers that explain most incidents
redis-cli INFO memory | grep -E 'used_memory_human|used_memory_peak_human|mem_fragmentation_ratio'
redis-cli INFO stats  | grep -E 'evicted_keys|expired_keys|rejected_connections'
redis-cli INFO clients | grep -E 'connected_clients|blocked_clients'

mem_fragmentation_ratio is used_memory_rss / used_memory. Above about 1.5 means real fragmentation, and activedefrag yes can reclaim it. Below 1.0 means Redis is swapping, which is far worse than fragmentation and is an immediate incident.

Redis 8.0 adds INFO keysizes (a per-type size histogram) and a hotkeys section, so a section name that is missing usually means an older server rather than a typo.

Clients

redis-cli CLIENT LIST                        # every connection, one line each
redis-cli CLIENT LIST TYPE pubsub            # normal | master | replica | pubsub
redis-cli CLIENT INFO                        # just this connection
redis-cli CLIENT ID
redis-cli CLIENT SETNAME importer            # shows up in CLIENT LIST and SLOWLOG
redis-cli CLIENT KILL ID 42
redis-cli CLIENT KILL ADDR 10.0.0.9:51234
redis-cli CLIENT KILL LADDR 10.0.0.1:6379 TYPE normal SKIPME yes
redis-cli CLIENT NO-EVICT on                 # 7.0+, exempt this client from eviction
redis-cli CLIENT NO-TOUCH on                 # 7.2+, do not update LRU/LFU on my reads
redis-cli CLIENT UNPAUSE
redis-cli CLIENT PAUSE 5000 WRITE            # stall writes, for a controlled failover

CLIENT LIST fields worth reading: age (connection lifetime), idle (seconds since the last command), cmd (the last command run), multi (queued commands, -1 when not in a transaction), sub/psub, and omem plus tot-net-out for output-buffer pressure. Always CLIENT SETNAME from your app, because "which of these 400 connections is the importer" is otherwise unanswerable.

CLIENT NO-TOUCH on is what a debugging session should set, so your own --bigkeys sweep does not reshuffle the LRU ordering of production keys.

DEBUG and benchmarking

redis-cli DEBUG OBJECT hu:user:1042
# Value at:0x... refcount:1 encoding:listpack serializedlength:24 lru:... lru_seconds_idle:0
redis-cli DEBUG JMAP                # no-op on most builds
redis-cli DEBUG SLEEP 1             # block the server for 1 second, ON PURPOSE
redis-cli DEBUG SET-ACTIVE-EXPIRE 0 # disable the expiry cycle, for tests
redis-cli DEBUG QUICKLIST-PACKED-THRESHOLD 100

DEBUG is an unstable internal command set. DEBUG SLEEP blocks the whole server, DEBUG SEGFAULT crashes it deliberately, and DEBUG SET-ACTIVE-EXPIRE 0 breaks expiry until you set it back. Run these only against an instance you started yourself and can throw away. OBJECT ENCODING plus MEMORY USAGE give you the same useful information safely.

redis-benchmark -h host -p 6379 -q                     # quick summary of every test
redis-benchmark -t get,set -n 100000 -c 50 -P 16 -q    # ops, clients, pipeline depth
redis-benchmark -t set -n 100000 -d 1024 -q            # 1KB values
redis-benchmark -n 10000 -r 100000 -t set -q           # 100k random keyspace
redis-benchmark -n 1000 script load "return 1"
redis-benchmark --dbnum 9 -t set -n 1000               # keep it out of db 0

-P is the pipeline depth and it dominates the result, so a headline number quoted without -P is meaningless. redis-benchmark writes keys (key:__rand_int__ and similar), so point it at a throwaway instance or at least a spare --dbnum.

Backups and dumps

redis-cli --rdb /tmp/backup.rdb                # ask the server for a fresh RDB, over the wire
redis-cli --functions-rdb /tmp/funcs.rdb       # only the function libraries
redis-cli BGSAVE && redis-cli LASTSAVE         # snapshot in place, confirm it advanced

redis-cli DUMP hu:user:1042 | xxd | head -2    # one key, serialized
redis-cli -h src DUMP hu:k                     # then RESTORE on the target
redis-cli MIGRATE targethost 6379 hu:k 0 5000 COPY REPLACE   # move one key live

--rdb is the remote-backup tool: it triggers a save and streams the file to your machine, so it needs no filesystem access to the server. DUMP and RESTORE are per key and the payload is version-checked, so a dump from a newer Redis may be rejected by an older one.

A triage order that works

1. INFO memory and INFO stats. Is it evicting, swapping, or fragmenting? 2. INFO clients. Are connections or blocked clients climbing? 3. SLOWLOG GET 20. Is one command family slow? 4. INFO commandstats sorted by usec_per_call. Which command dominates total time? 5. --bigkeys or --memkeys. Is one enormous key behind the O(n) commands? 6. --latency from a client host, then --intrinsic-latency on the server. Is it Redis, the network, or the kernel? 7. INFO persistence. Did a fork or a failed save pause everything? 8. MONITOR for a few seconds, last, only if the above did not identify it.