Installing Redis, redis-cli and RESP basics

Server and Redis Stack options, the redis-cli commands worth memorising, the RESP protocol, SCAN instead of KEYS, and reading INFO.

Getting a server running

# container, the least surprising option in development
docker run -d --name redis -p 6379:6379 redis:7-alpine \
  redis-server --save 60 1 --appendonly no

# Redis Stack adds JSON, search, time series and Bloom filters
docker run -d --name redis-stack -p 6379:6379 redis/redis-stack-server:latest

redis-cli -h 127.0.0.1 -p 6379 ping          # PONG
redis-cli -u redis://:password@host:6379/0

# inside the CLI
127.0.0.1:6379> INFO server | head -20
127.0.0.1:6379> CONFIG GET maxmemory
127.0.0.1:6379> DBSIZE
127.0.0.1:6379> MONITOR                    # heavy: development only
  • Redis is single-threaded for command execution. One slow command blocks every other client, which is why the O(N) commands matter so much.
  • Persistence defaults differ between packages: a container without a volume loses everything on restart, which is fine for a cache and disastrous for a queue.
  • The database number in the URL (/0) is a namespace inside one instance, not an isolation boundary. Use separate instances or key prefixes for tenants.
  • redis-cli --latency measures round-trip time and is the first thing to check when a client reports slowness.
💡
Run redis-cli --bigkeys --memkeys against a copy of production rather than the live instance: both walk the entire keyspace and the memory variant also samples values. On a large dataset that is real load.

RESP, the wire protocol

Client:  *3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
Server:  +OK\r\n

Client:  *2\r\n$3\r\nGET\r\n$3\r\nfoo\r\n
Server:  $3\r\nbar\r\n

# types
#   +simple string   -error   :integer   $bulk string   *array
#   RESP3 adds: %map  ~set  >push  _null  ,double  #boolean
  • A request is an array of bulk strings. Because there is no request framing beyond the length prefixes, a client that mis-encodes a length corrupts the connection for every following command.
  • RESP3 lets a client receive pushes (pub/sub messages and client-side cache invalidations) on the same connection as normal replies.
  • Pipelining sends several commands without waiting for the replies; the server replies in order. It removes round trips, and it does not make the commands themselves faster.
  • Use raw mode (redis-cli --no-raw) to see what the protocol actually returned, which is how you debug a client library returning unexpected types.
# a pipeline of 10k commands, one round trip
redis-cli --pipe < commands.txt

# measure the cost of a round trip
redis-cli --latency-history -i 5

# a slow-motion trace of big or slow commands
redis-cli slowlog get 10
redis-cli --intrinsic-latency 5

Navigating the keyspace

127.0.0.1:6379> KEYS user:*              # NEVER in production: blocks the server
127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 100
127.0.0.1:6379> SSCAN myset 0 COUNT 100
127.0.0.1:6379> HSCAN myhash 0 COUNT 100
127.0.0.1:6379> TYPE user:42
127.0.0.1:6379> TTL user:42
127.0.0.1:6379> OBJECT ENCODING user:42   # listpack, intset, skiplist, hashtable...
127.0.0.1:6379> MEMORY USAGE user:42
127.0.0.1:6379> INFO keyspace
127.0.0.1:6379> INFO memory | grep -E "used_memory_human|maxmemory_human"
CommandCostUse
KEYS patternO(N), blocksNever in production - debugging on a small dataset at most
SCANO(1) per callProduction iteration; may return duplicates
SCAN with COUNTA hint, not a limitThe server may return more or fewer than COUNT
OBJECT ENCODINGO(1)Explains memory and which operations are cheap
DBSIZEO(1)Total keys in the current database
  • SCAN is a cursor over a hash table that can be rehashing. It guarantees every element present for the whole iteration is returned at least once, so you must tolerate duplicates.
  • TYPE mismatches are the most common cause of a WRONGTYPE error; a key whose type changed between deployments is a data migration, not a cache miss.
  • OBJECT ENCODING tells you whether a small hash is a compact listpack or a full hash table - the same logical data can differ by an order of magnitude in memory.

FAQ

Do I need Redis Stack or plain Redis?
Plain Redis unless you need JSON documents, full-text search, time series or probabilistic types. Redis Stack is a superset and costs memory for modules you may not use, so start plain and add modules when a concrete requirement appears.
Why does my SCAN return the same key twice?
Because the hash table can rehash while you iterate. Deduplicate in your client and iterate until the returned cursor is 0 - that is the documented contract, not a bug.

Data types and the commands that matter Key design, memory and eviction

Last refreshed 2026-09-18.