← Cheatsheets

CHEATSHEET · MESSAGING & DATA · SENIOR INTERVIEW

Redis — The Senior Interview Cheatsheet.

redis caching data-store interview-prep
Redis is a single-threaded, in-memory data-structure server. Single-threaded for command execution means one slow command stalls everyone — so the senior story is all about O(N) commands, memory, persistence fork pauses, and the replication/HA topology. It's not "a cache"; it's a toolbox of data structures with optional durability.

1. Why single-threaded matters

  • Commands run on one thread in an event loop → atomic by nature (no locks between commands), but one O(N) command blocks all clients.
  • Redis 6+ adds threaded I/O (socket read/write only); command execution stays single-threaded. Redis 7 keeps this model.
  • Implication: never run KEYS *, big SMEMBERS/HGETALL, or a long Lua script in prod — they freeze the loop.

2. Data types & when to use them

TypeUse / key commands
StringCache value, counter. SET/GET, INCR, SETEX, SETNX, GETSET.
HashObject/fields. HSET/HGET/HGETALL, HINCRBY. Memory-efficient for small objects.
ListQueue/stack. LPUSH/RPUSH, LPOP/RPOP, BLPOP (blocking), LRANGE.
SetUnique members, set ops. SADD, SISMEMBER, SINTER/SUNION.
Sorted Set (ZSet)Leaderboard, priority, time index. ZADD, ZRANGE, ZRANGEBYSCORE, ZRANK.
StreamAppend-only log + consumer groups (Kafka-lite). XADD, XREADGROUP, XACK.
Bitmap / HyperLogLogFlags / approx-cardinality. SETBIT, BITCOUNT; PFADD/PFCOUNT (~0.81% error, 12KB).
GeoGeospatial (zset under the hood). GEOADD, GEOSEARCH.

3. Keys, TTL & expiry

EXPIRE key 60 ; PEXPIRE key 1500 ; TTL key ; PERSIST key
SET key val EX 60 NX           # set if-absent with TTL (atomic)
SCAN 0 MATCH user:* COUNT 100  # cursor iteration — NEVER KEYS * in prod
  • Expiry is lazy (on access) + active (background sampling) — an expired key can briefly linger in memory until reaped.
  • On a replica, keys don't expire on their own — the primary sends DEL on expiry (avoids replicas diverging).
KEYS * is a production footgun KEYS is O(N) over the whole keyspace and blocks the single thread — a multi-second freeze on millions of keys. Always SCAN (cursor, non-blocking, bounded work).

4. Memory & eviction

CONFIG GET maxmemory ; CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru
INFO memory   # used_memory, mem_fragmentation_ratio, maxmemory_policy
PolicyBehaviour
noevictionReject writes when full (default). Good for a durable store, bad for a cache.
allkeys-lru / lfuEvict least-recently / least-frequently used across all keys. Cache default.
volatile-lru / ttl / randomEvict only among keys with a TTL.
cache with noeviction = outage A cache using noeviction stops accepting writes when full instead of dropping cold keys. Use allkeys-lru/lfu and set maxmemory below the container limit (else the kernel OOM-kills the process).

5. Persistence — RDB vs AOF

RDBAOF
WhatPoint-in-time snapshot (fork + dump)Append-only log of write commands
RecoveryFaster load, lose data since last snapshotLess data loss (fsync everysec), slower replay
CostFork = copy-on-write memory spikeDisk-heavy; periodic rewrite/compaction

appendfsync everysec is the balanced default (≤1s loss). Many run both (AOF for durability + RDB for fast restart). BGSAVE/BGREWRITEAOF fork in the background — the fork's copy-on-write can double memory under heavy writes.

6. Transactions, Lua & pipelining

  • MULTI/EXEC — queue commands, run atomically (no interleaving). Not rollback-on-error; WATCH adds optimistic locking (CAS) — abort if a watched key changed.
  • Lua scripts (EVAL/EVALSHA) run atomically server-side — ideal for read-modify-write (rate limiters, locks). Keep them short (they block the loop).
  • Pipelining — send many commands without waiting for each reply → fewer round trips, big throughput win. Not atomic; just batched.

7. Patterns (the interview favourites)

  • Cache-aside: read cache → miss → read DB → SET with TTL. Handle stampedes with jittered TTL / locks / request coalescing.
  • Distributed lock: SET key token NX PX 30000; release via a Lua compare-and-del (only if token matches). For HA correctness, Redlock — but it's debated; a single instance + fencing token is often enough.
  • Rate limiting: INCR + EXPIRE (fixed window), or a Lua sliding-window with a ZSet.
  • Leaderboard: ZSet ZADD/ZREVRANGE.
  • Queue / stream: Lists (BLPOP) for simple; Streams + consumer groups for ack/replay.
naive SET NX lock is unsafe Locking with SETNX then a plain DEL can delete someone else's lock after your TTL expired. Store a unique token and release with a Lua check-and-delete; add a fencing token if the protected resource supports it.

8. Replication, Sentinel & Cluster

  • Replication — async primary → replicas; replicas serve reads (can be stale). WAIT can require N replicas ack a write (not full sync durability).
  • Sentinel — monitors + automatic failover for a single-primary setup (promotes a replica, updates clients). HA, not sharding.
  • Cluster — sharding across nodes via 16384 hash slots (CRC16(key) % 16384); each primary owns a slot range + has replicas. Multi-key ops must share a slot (use hash tags {user1}:profile).
async replication can lose acked writes A write acked by the primary may not have reached a replica before failover — small data-loss window. WAIT reduces it but isn't synchronous durability. Know this trade-off.

9. Performance & diagnosis

redis-cli --latency / --latency-history     # round-trip latency
redis-cli SLOWLOG GET 20                     # slowest commands + args
redis-cli LATENCY DOCTOR                     # human latency analysis
redis-cli INFO commandstats                  # usec_per_call per command
redis-cli --bigkeys / --hotkeys              # memory hogs / hot keys
redis-cli INFO clients   # blocked_clients, connected_clients

Top causes of latency: O(N) commands on big keys, fork pauses (RDB/AOF rewrite), swap (never let Redis swap), big-value (de)serialization, MONITOR left running, THP enabled on the host. Use UNLINK (async free) not DEL for big keys.

10. Senior interview Q&A

  • Why is single-threaded a feature, not a bug?No lock contention, atomic commands, predictable; bottleneck is memory/network not CPU. Downside: one O(N) command blocks all — so avoid KEYS/big-key ops. I/O is threaded in 6+.
  • RDB vs AOF?RDB = periodic snapshot (fast restart, more loss). AOF = command log (less loss with everysec, slower replay). Often run both.
  • How does eviction work / which policy for a cache?When maxmemory hit, evict per maxmemory-policy. Cache → allkeys-lru/lfu; durable store → noeviction (but then full = write errors).
  • Is MULTI/EXEC a real transaction?Atomic + isolated, but no rollback on logic errors. WATCH gives optimistic CAS. For atomic read-modify-write, prefer a Lua script.
  • How do you build a safe distributed lock?SET key token NX PX ttl; release via Lua that deletes only if token matches; add a fencing token. Redlock for multi-node (debated).
  • Sentinel vs Cluster?Sentinel = HA/failover for single-primary (no sharding). Cluster = sharding via 16384 hash slots + per-shard replicas.
  • How does Cluster shard keys?CRC16(key) % 16384 → slot → node. Multi-key ops must hit one slot; force co-location with hash tags {tag}.
  • Can Redis lose data?Yes — async replication + failover has a loss window; RDB loses since last snapshot. WAIT/AOF reduce it. It's not a system of record by default.
  • How do you prevent a cache stampede?Jittered TTLs, a short lock so one request rebuilds, request coalescing, or stale-while-revalidate.
  • Why did latency spike with no traffic change?Usually a fork pause (BGSAVE/AOF rewrite), an O(N) command on a big key, swap, or THP. Check SLOWLOG + LATENCY DOCTOR.
  • DEL vs UNLINK?DEL frees synchronously (blocks on a huge key); UNLINK frees in a background thread.
  • Redis vs Memcached?Memcached = simple multi-threaded LRU cache. Redis = rich data structures, persistence, replication, pub/sub, scripting, cluster.
  • When NOT to use Redis?As the only system of record for critical data (loss window), for datasets that don't fit RAM affordably, or for complex queries/joins (use a DB).
← prev: Kafka next: EMQX →
© cvam — written in plaintext, served warm