Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Redis Patterns & Internals

Caching Patterns

Cache-Aside (Lazy Loading)

Read:  App → Cache → (miss) → DB → Cache → App
Write: App → DB → Invalidate Cache

Most common pattern. App manages cache explicitly.

Write-Through

Write: App → Cache → DB
Read:  App → Cache → (always hit)

Cache always has latest data. Higher write latency.

Write-Back (Write-Behind)

Write: App → Cache → (async) → DB

Fast writes. Risk of data loss if cache crashes before flushing.

Eviction Policies

PolicyBehaviorUse Case
noevictionReturn error on full cacheCritical data, never lose
allkeys-lruEvict least recently usedGeneral purpose
volatile-lruEvict LRU from keys with TTLMixed cache + persistent
allkeys-lfuEvict least frequently usedLong-term cache
volatile-ttlEvict shortest TTL firstShort-lived cache

Persistence

RDB (Snapshot)

save 900 1      # Save if ≥1 key changed in 900 seconds
save 300 10     # Save if ≥10 keys changed in 300 seconds

Point-in-time snapshots. Compact. Possible data loss between snapshots.

AOF (Append-Only File)

appendonly yes
appendfsync everysec  # fsync every second

Logs every write operation. More durable. Larger files. AOF rewrite for compaction.

Comparison

AspectRDBAOF
DurabilityPossible data loss (between snapshots)Max 1 second loss
RecoveryFast (load snapshot)Slower (replay log)
File sizeCompactLarger (can rewrite)
ForkYes (blocks briefly on large datasets)Yes (rewrite)

Redis Cluster

Client → Cluster (16384 hash slots)
         ├── Node A (slots 0-5460)    [master + replica]
         ├── Node B (slots 5461-10922) [master + replica]
         └── Node C (slots 10923-16383) [master + replica]
  • Automatic sharding by CRC16(key) % 16384
  • Each master has at least one replica
  • Automatic failover (Sentinel or Cluster mode)
  • Resharding without downtime

Distributed Locks

# Acquire lock (SET NX + EX)
SET lock:resource "unique-token" NX EX 30

# Release lock (Lua script for atomicity)
EVAL "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock:resource "unique-token"

Rate Limiting

# Sliding window with sorted sets
ZADD rate:user:1 <timestamp> <unique-id>
ZREMRANGEBYSCORE rate:user:1 0 <timestamp - window>
ZCARD rate:user:1
# If count > limit → reject

Interview Questions

Q: What is the difference between Redis and Memcached? A: Redis supports rich data structures (lists, sets, sorted sets, hashes, streams), persistence (RDB/AOF), replication, Lua scripting, pub/sub. Memcached is simpler (key-value only), multithreaded, no persistence. Redis is more feature-rich; Memcached is simpler for basic caching.

Q: How does Redis achieve high performance? A: (1) In-memory storage, (2) single-threaded command execution (avoids locks and context switching on the command path; Redis 6.0+ optional multi-threaded I/O for network reads/writes via io-threads), (3) efficient data structures (ziplist, intset, skiplist), (4) I/O multiplexing (epoll), (5) pipeline/batch operations.

Q: How do you handle Redis running out of memory? A: (1) Set maxmemory, (2) configure eviction policy (LRU/LFU), (3) use TTLs on cached keys, (4) shard across cluster, (5) monitor memory usage, (6) compress values, (7) use hashes instead of many small keys (more memory efficient).

References