Redis & Memcached Deep Dive
📖 Concept
Redis and Memcached are the top in-memory caching systems.
Redis vs Memcached
| Feature | Redis | Memcached |
|---|---|---|
| Data structures | Strings, Lists, Sets, Sorted Sets, Hashes, Streams | Strings only |
| Persistence | Optional (RDB/AOF) | None |
| Replication | Built-in primary-replica | None |
| Pub/Sub | Built-in | None |
| Scripting | Lua (atomic ops) | None |
| Threading | Single-threaded (I/O threads in 6.0+) | Multi-threaded |
| Speed | ~100K ops/sec | ~100K ops/sec |
When to Use Each
- Redis: Need data structures, persistence, pub/sub, or multiple use cases
- Memcached: Simple key-value caching with maximum memory efficiency
Redis Use Cases in System Design
| Use Case | Redis Feature |
|---|---|
| Caching | GET/SET + TTL |
| Sessions | Hash + TTL |
| Rate limiting | Sorted Set |
| Leaderboards | Sorted Set |
| Pub/Sub | PUBLISH/SUBSCRIBE |
| Distributed locks | SETNX + TTL |
| Counters | INCR/DECR |
| Geospatial | GEOADD/GEORADIUS |
Pro tip: Say "Redis" in interviews. It's the industry standard.
💻 Code Example
1// ============================================2// Redis Patterns for System Design3// ============================================45const Redis = require('ioredis');6const redis = new Redis();78// ---------- Distributed Lock ----------9class RedisLock {10 constructor(redis) { this.redis = redis; }1112 async acquire(lockName, ttlMs = 10000) {13 const lockKey = `lock:\${lockName}`;14 const lockValue = `\${Date.now()}:\${Math.random()}`;15 const result = await this.redis.set(lockKey, lockValue, 'PX', ttlMs, 'NX');16 return result === 'OK' ? { acquired: true, value: lockValue, key: lockKey } : { acquired: false };17 }1819 async release(lockKey, lockValue) {20 const lua = 'if redis.call("GET",KEYS[1])==ARGV[1] then return redis.call("DEL",KEYS[1]) else return 0 end';21 await this.redis.eval(lua, 1, lockKey, lockValue);22 }23}2425// ---------- Leaderboard ----------26async function leaderboard() {27 await redis.zadd('leaderboard', 1500, 'alice', 2300, 'bob', 1800, 'carol');28 const top10 = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES');29 const rank = await redis.zrevrank('leaderboard', 'alice');30 await redis.zincrby('leaderboard', 100, 'alice');31 console.log('Top 10:', top10, 'Alice rank:', rank + 1);32}3334// ---------- Session Store ----------35async function sessions() {36 const sid = 'sess_abc';37 await redis.hmset(`session:\${sid}`, { userId: '123', role: 'admin', loginAt: Date.now().toString() });38 await redis.expire(`session:\${sid}`, 3600);39 const role = await redis.hget(`session:\${sid}`, 'role');40 console.log('Role:', role);41}4243// ---------- Geospatial (Uber-like) ----------44async function geo() {45 await redis.geoadd('drivers', -122.4194, 37.7749, 'driver_1', -122.4089, 37.7835, 'driver_2');46 const nearby = await redis.georadius('drivers', -122.4194, 37.7749, 5, 'km', 'WITHDIST', 'ASC', 'COUNT', 10);47 console.log('Nearby drivers:', nearby);48}4950leaderboard(); sessions(); geo();
🏋️ Practice Exercise
Redis for Uber: Design Redis architecture for 5M driver locations updated every 4 seconds. What data structures?
Redis vs DB: For each — sessions, product catalog, view counter, order history, rate limiting — choose Redis or PostgreSQL.
Redis Cluster: Need 500GB cache, nodes max 64GB. Design cluster: masters, replicas, sharding, failover.
Redis Persistence: Compare RDB snapshots vs AOF. When use each? When disable persistence?
⚠️ Common Mistakes
Using Redis without persistence when data must survive restarts — enable RDB or AOF.
Storing 5MB objects per key — wastes memory, increases latency. Break into smaller entries or use hashes.
Not setting maxmemory — Redis uses all RAM and gets OOM-killed. Always set limit + eviction policy.
Using Pub/Sub for reliable delivery — it's fire-and-forget; disconnected subscribers lose messages. Use Redis Streams or Kafka.
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Redis & Memcached Deep Dive