Redis cheat sheet
A scannable Redis reference: 26 short snippets across 12 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| Data types and the commands that matter | A Redis string holds up to 512 MB of binary-safe bytes, which means it also stores JSON, a serialised object, or a | lesson |
| Expiry and caching patterns | The dominant pattern is cache-aside: read from Redis, and on a miss read from the database, write the value back with a | lesson |
| Pub/sub, queues and persistence | Replication is asynchronous by default, so a primary that fails can lose writes that no replica has yet received. WAIT | lesson |
| 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 | lesson |
| Key design, memory and eviction | Mixing a cache and a queue in one instance means the cache policy can silently delete queued work. Separate instances | lesson |
| Transactions, Lua scripting and atomicity | Any read-then-write sequence issued as two round trips is a race. If the correctness of your feature depends on the | lesson |
| Streams and reliable queue processing | The ~ in MAXLEN ~ makes trimming approximate, which is far cheaper because Redis can remove whole radix-tree nodes | lesson |
| Distributed locks and rate limiting | Correct SET NX PX locks, the token that makes release safe, the real caveats of Redlock, and token bucket and | lesson |
| Everyday patterns: sessions, leaderboards and counters | Session storage with sliding expiry, sorted-set leaderboards with ties and time decay, atomic counters, HyperLogLog | lesson |
| Security: ACLs, TLS and hardening | ACL users with key and command patterns, TLS configuration, disabling dangerous commands, protected mode, and network | lesson |
| Performance, pipelining and monitoring | Pipelining and batching, latency diagnosis, SLOWLOG, client-side caching, hot keys, fork stalls and the metrics worth | lesson |
| Replication, Sentinel and high availability | Clients must ask Sentinel for the current primary rather than caching an address. Every mature client library has a | lesson |
Quick snippets
Data types and the commands that matter
Atomicity and the O(N) trap
MULTI
INCR stats:orders
ZADD leaderboard 10 alice
EXEC # both run, in order, with nothing in between
EVAL "return redis.call('GET', KEYS[1])" 1 user:42:name
SCAN 0 MATCH user:42:* COUNT 100 # safe cursor-based iteration
OBJECT ENCODING leaderboard # listpack or skiplist?
MEMORY USAGE user:42Full lesson: Data types and the commands that matter →
Expiry and caching patterns
How expiry works
SET cache:user:42 '{"name":"Ada"}' EX 300
EXPIRE cache:user:42 300
TTL cache:user:42 # -1 has no TTL, -2 does not exist
PERSIST cache:user:42 # remove the TTL
SET lock:job:9 worker-3 NX EX 30 # atomic: only one worker wins
CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru
INFO memoryFull lesson: Expiry and caching patterns →
Pub/sub, queues and persistence
Reliable queue patterns
# naive: the message is gone if the worker dies after BRPOP returns
BRPOP queue:email 5
# reliable: move to a per-worker processing list atomically, then remove on success
LMOVE queue:email processing:w3 LEFT RIGHT
LREM processing:w3 1 "m-1" # on success
LPUSH queue:email "m-1" # on failure: put it back
# a separate sweeper re-queues anything stuck too long
LRANGE processing:w3 0 -1
Persistence and replication
# redis.conf
save 900 1 # RDB snapshot after 1 change in 900s
save 300 10
appendonly yes # AOF on
appendfsync everysec # fsync once per second: at most ~1s of writes lost
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# on a replica
REPLICAOF 10.0.0.10 6379
WAIT 1 100 # block until 1 replica acknowledges, max 100 msFull lesson: Pub/sub, queues and persistence →
Installing Redis, redis-cli and RESP basics
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
RESP, the wire protocol
# 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"Full lesson: Installing Redis, redis-cli and RESP basics →
Key design, memory and eviction
Key design
# colon-separated, type-prefixed keys
SET user:42:profile:1 '{"name":"Ada"}'
HSET cart:42:items sku1 2 sku2 1
ZADD board:daily:2026-09-18 1500 user:42
EXPIRE user:42:profile:1 3600
# hash tags force related keys onto the same cluster slot
# user:{42}:profile user:{42}:orders -> both hash to slot(user:{42})
# note the braces: only the part inside them is used for the slot
Eviction policies
CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru
CONFIG SET maxmemory-samples 10
# check what is actually happening
INFO stats | grep evicted_keys
INFO memory | grep -E "maxmemory_policy|mem_fragmentation_ratio"
Eviction policies
# never mix cache and durable data in one instance
# instance A: cache only
maxmemory-policy allkeys-lru
# instance B: locks, queues, sessions
maxmemory-policy noeviction
# and alert on evicted_keys > 0 and on rejected_connectionsFull lesson: Key design, memory and eviction →
Transactions, Lua scripting and atomicity
Lua scripting
-- rate limit: increment and set a TTL only on the first hit
-- KEYS[1] = counter key, ARGV[1] = limit, ARGV[2] = window seconds
local current = redis.call('INCR', KEYS[1])
if current == 1 then
redis.call('EXPIRE', KEYS[1], ARGV[2])
end
if current > tonumber(ARGV[1]) then
return 0
end
return 1
Lua scripting
redis-cli --eval ratelimit.lua counter:user:42 , 100 60
# or inline
EVAL "return redis.call('GET', KEYS[1])" 1 mykey
# load once, run by hash: the preferred production pattern
SCRIPT LOAD "return redis.call('GET', KEYS[1])"
EVALSHA <sha1> 1 mykey
SCRIPT EXISTS <sha1>
Redis Functions and atomic patterns
#!lua name=mylib
redis.register_function('claim_job', function(keys, args)
local job_id = redis.call('LMOVE', keys[1], keys[2], 'LEFT', 'RIGHT')
if not job_id then return false end
redis.call('HSET', keys[3], job_id, args[1])
return job_id
end)Full lesson: Transactions, Lua scripting and atomicity →
Streams and reliable queue processing
Adding and reading
XADD events * type order_placed order_id 42 amount 1999
XADD events * type order_paid order_id 42
XLEN events
XRANGE events - +
XREVRANGE events + - COUNT 10
XREAD COUNT 10 BLOCK 5000 STREAMS events $
# only messages newer than a known id, for catch-up after a restart
XREAD COUNT 100 STREAMS events 1758200000000-0
Consumer groups
# reclaim messages a dead worker left behind after 60s of idle
XAUTOCLAIM events workers worker-2 60000 0-0 COUNT 50
# trim to the last 100k entries when adding
XADD events MAXLEN ~ 100000 * type tick value 1.23
# or trim by time: keep roughly the last day
XTRIM events MINID ~ 1758000000000
Reliable processing patterns
# find consumers that have stopped acking
XPENDING events workers - + 1000
# then, per consumer, compare delivered and acknowledged counts
XINFO CONSUMERS events workersFull lesson: Streams and reliable queue processing →
Distributed locks and rate limiting
A lock that actually works
# acquire: atomic set-if-absent with an expiry and an owner token
SET lock:order:42 <token> NX PX 30000
# release: compare and delete, in one atomic step (see the Lua script earlier)
# never: DEL lock:order:42 -- you may delete someone else's lock
# extend only if you still hold it: renewal, not acquisition
# repeated in a heartbeat while the work continues
# a fencing token is the only real protection
# every write to the protected resource carries the token,
# and the resource rejects any token lower than the highest seen
Rate limiters
-- sliding window log: precise, memory proportional to the limit
-- KEYS[1] = key, ARGV[1] = now ms, ARGV[2] = window ms, ARGV[3] = limit
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, ARGV[1] - ARGV[2])
local count = redis.call('ZCARD', KEYS[1])
if count >= tonumber(ARGV[3]) then
return 0
end
redis.call('ZADD', KEYS[1], ARGV[1], ARGV[1] .. '-' .. math.random(1000000))
redis.call('PEXPIRE', KEYS[1], ARGV[2])
return 1Full lesson: Distributed locks and rate limiting →
Everyday patterns: sessions, leaderboards and counters
Session storage
HSET session:<id> user_id 42 role admin csrf <token> ip 203.0.113.9
EXPIRE session:<id> 1800
# sliding expiry: refresh on every request, but not on every request
# - refreshing on each call makes the key hot and the TTL meaningless
# - refresh only when more than 25 percent of the TTL has elapsed
# find a session by user for forced logout
SET user:42:session <session-id>
# log out everywhere
DEL session:<id> user:42:session
Leaderboards with sorted sets
# keep only the top 10k: sorted sets do not trim themselves
ZREMRANGEBYRANK board:global 0 -10001
# combine score and timestamp so ties break by who reached it first
# score = points, tie-break = (a large constant - unix seconds) / 1e6
# then ZREVRANGE gives the earlier achiever firstFull lesson: Everyday patterns: sessions, leaderboards and counters →
Security: ACLs, TLS and hardening
TLS and transport
redis-cli --tls --cacert /etc/redis/tls/ca.crt \
--cert /etc/redis/tls/client.crt --key /etc/redis/tls/client.key \
-h redis.internal -p 6379 PING
Network and operational hardening
# verify what is exposed before you ship
ss -ltnp | grep redis
redis-cli ACL WHOAMI
redis-cli CONFIG GET bind
redis-cli CONFIG GET requirepass
redis-cli INFO server | grep -E "redis_version|config_file"Full lesson: Security: ACLs, TLS and hardening →
Performance, pipelining and monitoring
Diagnosing latency
redis-cli --latency # continuous round-trip measurement
redis-cli --latency-history -i 5 # over time, shows spikes
redis-cli --intrinsic-latency 5 # how fast can this box run at all
redis-cli --stat # live ops/s, memory, clients
redis-cli SLOWLOG GET 10
redis-cli CONFIG SET slowlog-log-slower-than 10000 # 10 ms
redis-cli CONFIG SET latency-monitor-threshold 100 # 100 ms
redis-cli LATENCY HISTORY command
redis-cli LATENCY RESET
redis-cli INFO commandstats | sort -t= -k2 -rn | headFull lesson: Performance, pipelining and monitoring →
Replication, Sentinel and high availability
Replication
# on the primary
bind 10.0.0.10
requirepass ... # or an ACL user
masterauth ...
# on each replica
replicaof 10.0.0.10 6379
replica-read-only yes
replica-serve-stale-data yes
repl-backlog-size 64mb
min-replicas-to-write 1
min-replicas-max-lag 10
Replication
redis-cli INFO replication
# role:master
# connected_slaves:2
# slave0:ip=10.0.0.11,state=online,offset=12345,lag=0
redis-cli -h 10.0.0.11 INFO replication | grep master_repl_offset
# WAIT reports how many replicas acknowledged a write
redis-cli SET important value
redis-cli WAIT 1 100 # at least 1 replica, within 100 ms
Sentinel and failover
# sentinel.conf, one file per Sentinel process, three or more across hosts
port 26379
sentinel monitor mymaster 10.0.0.10 6379 2
sentinel auth-pass mymaster ...
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1Full lesson: Replication, Sentinel and high availability →
FAQ
Is this Redis cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
SQL MySQL PostgreSQL MongoDB SQLite
Last refreshed 2026-09-27.