See It Flow
Interactive guide · 5 chapters · ~25 min read

Interview & Revision

Interview-ready Redis knowledge — the questions that show up, the answers a Staff engineer would give, plus a quick revision refresher and a cheat sheet you can skim the morning of.

Mangesh MandlikLast updated:
01 · Warm-up

One-Liners You Must Own

Short, precise answers to the most common warm-up questions. Own these cold.

What is Redis?

An in-memory data structure server — command execution is serialized on the main thread, network-attached, supports strings, lists, hashes, sets, sorted sets, streams, and more, with optional persistence and replication.

Why is Redis fast?

RAM instead of disk, serialized command execution on the hot path, cache-friendly data structures, and efficient protocol handling.

What's a sorted set?

A set where each member has a floating-point score; members are kept sorted by score. Backed by a skip list + hash map. O(log N) inserts, O(log N + K) range queries.

What is RDB vs AOF?

RDB is a periodic point-in-time snapshot to a .rdb file — compact, fast to load, can lose everything since the last snapshot. AOF is an append-only command log — small durability window (typically ≤1 sec with appendfsync everysec), larger file, slower restart.

How does replication work?

Asynchronous. Primary streams every write to replicas via a replication buffer. Replicas do a full sync on first connect (RDB snapshot + backlog), then incremental sync. Primary doesn't wait for ACKs — writes can be lost on primary failure.

What does Sentinel do?

Watches Redis primary + replicas. Detects primary failure via quorum. Elects a leader Sentinel to run the failover. Promotes the most up-to-date replica. Notifies clients via pub/sub. Actual failover time depends on detection settings, topology, network conditions, and client reconnection behavior.

What is Redis Cluster?

Built-in horizontal sharding. Keyspace divided into 16 384 hash slots via CRC16(key) mod 16384. Each primary owns a range of slots. Clients cache slot→node mapping and route commands directly. Multi-key ops require hash tags ({user42}:...).

What's a distributed lock in Redis?

SET key owner NX PX ttl_ms. NX = only if not exists; PX = expire in ms. Release with a Lua script that deletes only if you're the owner. Basis of most Redis coordination patterns.

02 · The main event

Staff-Level Questions

The questions that decide whether the interview goes to the next round.

Walk me through what happens when a client does GET foo

1. Network read. The client's TCP packet arrives. If I/O threads are on, an I/O thread reads and parses the RESP frame. Otherwise the main loop does it.

2. Command dispatch. The main thread looks up GET in the command table, validates argument count.

3. Keyspace lookup. Hash the key with the main hash table's hash function. O(1) probe into the top-level dict.

4. Object fetch. Retrieve the robj (Redis object) — check its type (must be string), and if the string is encoded (embstr, raw, int), decode as needed.

5. Reply serialization. Frame the response as a RESP bulk string, queue it to the client's output buffer.

6. Async write. The next event loop iteration flushes the buffer to the socket. If I/O threads are on, an I/O thread does the write.

Total: the server-side work is usually small and consistent; end-to-end latency is dominated far more by the network round trip than by the hash lookup and reply framing.

How do you implement a rate limiter in Redis?

Fixed window (simplest):

INCR user:42:m1
EXPIRE user:42:m1 60  # sets or refreshes the TTL

Check the counter; reject if > threshold. Bugs on window boundaries ("burst at 59.9s and 0.1s = 2× limit"). Also note the INCR/EXPIRE pair has a race window if the client dies between commands; if you need correctness, make both steps atomic with Lua or with a version-aware pattern such as EXPIRE ... NX where supported.

Sliding window log:

ZADD user:42:requests <timestamp> <request-id>
ZREMRANGEBYSCORE user:42:requests -inf <now - 60s>
ZCARD user:42:requests

Accurate but O(N) memory in the window size.

Sliding window counter (best trade-off): two adjacent fixed windows; compute a weighted count based on how far into the current window you are. Bounded memory, near-accurate.

Token bucket: two Redis keys per user (tokens, last_refill_time); a Lua script atomically refills tokens based on elapsed time and decrements if enough are available. This is a widely used API rate-limiter pattern.

How does the Redlock algorithm work, and why is it controversial?

Redlock (proposed by Salvatore) is a distributed lock across N independent Redis instances. To acquire: try SET NX PX on all N instances; succeed if you got a majority (≥ N/2 + 1) within a small time budget. To release: DEL on all N.

The critique (Martin Kleppmann): Redlock assumes bounded clock drift and bounded process pauses. A stop-the-world GC pause that exceeds the lock TTL can cause two workers to think they hold the same lock. Kleppmann argues you need fencing tokens — the lock returns a monotonically increasing number, and the protected resource rejects operations with a stale token.

The nuanced take: The Redis distributed-locks documentation discusses this critique, including the need for fencing tokens and that Redis TTL expiry is not based on a monotonic clock, so clock shifts can break mutual exclusion. Redlock is a reasonable efficiency lock (avoid duplicate work occasionally), but do not rely on it alone to protect a critical section against process pauses or clock jumps. For anything financial, use fencing tokens or idempotency at the resource.

What are the trade-offs of running Redis Cluster vs functional sharding?

Redis Cluster wins: transparent to clients (mostly), automatic failover per-primary, can reshard live with CLUSTER RESHARD, native support for scaling out beyond one machine.

Cluster loses: every multi-key command must use hash tags or fails with CROSSSLOT, some commands (KEYS, SCAN, SORT, MIGRATE) become per-node, adds operational complexity (gossip protocol, cluster bus, CLUSTER MEET), client library must be cluster-aware.

Functional sharding wins: each Redis is a plain instance — everything works normally, no CROSSSLOT worries. Different instances can have different persistence/eviction policies. Blast radius is bounded — an outage on the session Redis doesn't affect the cache.

Functional sharding loses: doesn't scale a single workload beyond one instance. If your leaderboard Redis maxes out, you need Cluster or a re-model.

Interview line: "Most Redis deployments never need Cluster. Functional sharding gets you further than expected and keeps operational complexity low. Reach for Cluster when a single logical workload genuinely exceeds one instance's ceiling."

How would you make Redis persistent enough for financial data?

1. AOF with `appendfsync always` — every write waits for the AOF fsync, which reduces the local durability gap but does not create a blanket zero-loss guarantee across every storage and failure mode.

2. Replication with `WAIT n 5000` — after each critical write, block until at least N replicas report having processed the prior write commands or the timeout elapses. This improves confidence that replicas caught up, but Redis replication is still fundamentally asynchronous and a timeout only means the acknowledgement condition was not met in time — the primary may already have committed the write. Escalate/alert and rely on idempotent reconciliation rather than assuming the original write failed.

3. `min-replicas-to-write` config — refuse writes if fewer than N replicas are connected. Prevents accepting writes into a doomed-to-lose primary.

4. Idempotency at the target system. Redis is often a stepping-stone for a database write. Even with everything above, cover the last-mile risk by using natural idempotency keys (INSERT ... ON CONFLICT DO NOTHING in Postgres, versioned updates in DynamoDB).

Interview reality check: "Managed and enterprise Redis offerings may provide stronger durability options than a default OSS setup (for example stronger persistence settings such as fsync-per-write; note that WAIT is an acknowledgement check, not synchronous replication or a disk-durability guarantee), but check what each configuration actually guarantees. If you're building financial infrastructure and can't tolerate any window of loss, either verify that a managed/enterprise offering meets your durability requirement or use a different tool for that specific write path."

03 · Night before

60-Second Revision

The refresher for the morning of the interview.

Concepts

Redis = in-memory, command execution serialized on the main thread, data-structure server, network-attached.

Data structures: string, list, hash, set, sorted set (ZSet), stream, bitmap, HLL, geo.

Speed: RAM + simple structures + serialized command execution on the hot path + efficient protocol handling.

Persistence: RDB (snapshots) + AOF (command log). A common production choice when persistence matters is both, often with appendfsync everysec; pure-cache roles may choose differently.

Replication: async. Full sync on first connect, incremental after. Reads can go to replicas.

HA: Sentinel watches + fails over automatically. Odd number of Sentinels, separate failure domains.

Sharding: Cluster splits by CRC16 slot mod 16384. Multi-key ops need hash tags.

The four failure patterns to prevent

Slow command stall — rename KEYS and FLUSHALL; use SCAN.

Fork swap death — keep generous memory headroom for fork copy-on-write (a common rule of thumb is to stay well under about 60% of RAM), disable Transparent Huge Pages.

Thundering herd — jittered TTLs, single-flight fetch, stale-while-revalidate.

Silent data loss on failover — layer WAIT n, min-replicas-to-write, and idempotency at target; WAIT improves acknowledgement confidence but does not make replication consensus-based.

The 10 configs that matter

maxmemory, maxmemory-policy, save, appendonly, appendfsync, tcp-keepalive, slowlog-log-slower-than, io-threads, rename-command KEYS, rename-command FLUSHALL.

04 · Self-check

Quiz

Five questions to make sure the model stuck.

Q1. Why is Redis fast even though it's single-threaded?

Because Redis keeps working data in memory and executes commands serially on the hot path, it avoids per-command contention and interleaving between concurrent client commands. For simple operations, that keeps server-side work small and predictable. Redis parallelizes via I/O threads (network only) and via running multiple instances.

Q2. You SET a key, then read it from a replica and see the old value. Why?

Async replication. The primary applies the write locally and ACKs the client immediately; the replica gets the command a few ms later. Reading from the replica during that window sees the stale value. Fix if you can't tolerate it: read from the primary for that key, or use WAIT before the read to wait for replication.

Q3. You call `SET lock:x owner NX PX 5000` and got OK. Two minutes later you call `DEL lock:x`. What could go wrong?

The lock expired after 5 seconds. Someone else acquired it. Your DEL just deleted their lock. Now two workers think they hold it. Fix: never DEL a lock unconditionally — use a Lua script that checks the value matches your owner id, then deletes.

Q4. `KEYS user:*` is running for 3 seconds on a 10M-key instance. What happens to other clients?

They wait. Redis is single-threaded; KEYS blocks the main loop for its entire duration. All other clients queue and see multi-second latency. Fix: SCAN with a cursor and small COUNT hint — it's incremental and doesn't block. Rename KEYS in production so no one can do this accidentally.

Q5. You have RF=2 (primary + 1 replica), `acks` are meaningless in Redis, and you need to guarantee no data loss on primary failure. What do you do?

Redis's answer is WAIT n 5000 after each critical write — it blocks until N replicas acknowledge processing the write or the timeout elapses. Combined with min-replicas-to-write 1 (refuse writes if no replicas connected), it reduces the window where a primary accepts unreplicated writes, but it is still not a consensus-style guarantee and a timeout does not prove the primary write failed. For stronger guarantees, check what your managed or enterprise Redis offering actually guarantees, or move the durability guarantee to the downstream system with idempotency.

05 · Reference

Cheat Sheet

The command reference you'll actually reach for during an interview or a debug session.

Strings

redis
SET k v [EX 60] [NX|XX] [KEEPTTL]
GET k
INCR counter        # atomic +1
INCRBY counter 5    # atomic +5
MSET a 1 b 2 c 3    # batch set
MGET a b c          # batch get

Lists

redis
LPUSH q item        # push left
RPUSH q item        # push right
LPOP q              # pop left
RPOP q              # pop right
BLPOP q 0           # blocking pop, wait forever
LRANGE q 0 9        # first 10 items
LLEN q              # length

Hashes

redis
HSET user:42 name Alice age 30
HGET user:42 name
HGETALL user:42
HINCRBY user:42 views 1
HDEL user:42 age

Sets

redis
SADD tags red blue
SMEMBERS tags       # avoid on large sets — use SSCAN
SISMEMBER tags red
SINTER tags1 tags2  # set intersection
SCARD tags          # count

Sorted Sets

redis
ZADD leaderboard 5000 alice 4200 bob
ZRANGE leaderboard 0 9 REV WITHSCORES
ZINCRBY leaderboard 10 alice
ZRANGEBYSCORE leaderboard 1000 5000
ZREMRANGEBYSCORE leaderboard -inf 1000  # trim

Streams

redis
XADD orders * userId 42 amount 99
XLEN orders
XREAD COUNT 10 STREAMS orders 0
XGROUP CREATE orders workers $ MKSTREAM
XREADGROUP GROUP workers c1 COUNT 10 STREAMS orders >
XACK orders workers <id>
XPENDING orders workers    # unacked messages

Distributed Lock (Lua release)

redis
-- Acquire
SET lock:x owner-uuid NX PX 5000

-- Release (only if we still own it)
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:x owner-uuid

Ops

redis
INFO memory
INFO replication
CLIENT LIST
SLOWLOG GET 128
MEMORY USAGE key
MEMORY STATS
DEBUG SEGFAULT          # only in staging, tests failover
CLUSTER INFO
CLUSTER NODES
Key takeaways
  • Own the one-liners cold — SET NX PX, ZADD + ZRANGE, XADD + XREADGROUP.
  • The GET foo walkthrough should flow — that answer separates "knows Redis" from "has run Redis".
  • Rate limiting has four patterns — fixed window, sliding log, sliding counter, token bucket. Know when each wins.
  • Redlock is fine for duplicate-work prevention; not sufficient for hard mutual exclusion. Layer fencing tokens.
  • Functional sharding beats Cluster for most workloads. Cluster is for when one logical workload truly exceeds one instance.
  • For financial-grade durability: appendfsync always + WAIT n + min-replicas-to-write + idempotency at target as layered risk reduction; if you need stronger guarantees, verify what a managed/enterprise offering guarantees or use a different write path.