← Home
🏗Crack System Design with DSA AnimatorSystem DesignNEW
🏗 System Design›Architecture Styles

🟥Redis Fundamentals

In-memory data store for low-latency caching, counters, coordination, and realtime patterns.

📌 Key IdeaRedis is necessary when millisecond-level latency and high throughput matter. Use it for cache-aside, rate limiting, distributed locks, and short-lived shared state. Do not treat Redis as a complete replacement for your primary database.
🧩

Problem it solves

  • Primary databases can become bottlenecks for hot reads and bursty traffic.
  • Many systems need fast shared counters, TTL state, and lightweight coordination.
  • Redis provides low-latency in-memory primitives to offload core systems and improve responsiveness.
📖

Definition

Redis is an in-memory key-value data store with optional persistence and rich data structures (strings, hashes, lists, sets, sorted sets, streams, bitmaps, HyperLogLog).

✨

Why It Matters

  • Offloads hot reads from primary databases and reduces query latency.
  • Supports atomic operations for counters, TTL-based state, and distributed coordination.
  • Enables building realtime features (leaderboards, session state, pub/sub style notifications).
✅

When to Use

  • High-read APIs where DB offload and low latency are critical.
  • Short-lived session/token/state storage with TTL.
  • Fast counters, quotas, and distributed coordination primitives.
  • Leaderboard/realtime features using sorted sets/streams.
🚫

When NOT to Use

  • As the only durable store for critical financial data without appropriate persistence strategy.
  • Large analytical queries better suited for columnar/OLAP systems.
  • Use cases where eventual cache staleness is unacceptable without explicit invalidation strategy.
💻

Code Variations

1️⃣ Cache-aside read with TTLjava
String key = "user:" + userId;
String cached = redis.get(key);
if (cached != null) return deserialize(cached);

User user = userRepository.findById(userId).orElseThrow();
redis.setex(key, 300, serialize(user)); // 5 min TTL
return user;
Always set TTL unless key is intentionally permanent.
2️⃣ Fixed-window rate limiter sketchjava
String key = "rl:" + userId + ":" + epochMinute();
long count = redis.incr(key);
if (count == 1) redis.expire(key, 120); // keep for 2 mins
if (count > 100) throw new TooManyRequestsException();
For precise fairness at boundaries, prefer sliding-window/token-bucket logic.
3️⃣ Redis lock (basic ownership pattern)java
String lockKey = "lock:order:" + orderId;
String owner = UUID.randomUUID().toString();
boolean acquired = redis.set(lockKey, owner, SetArgs.setArgs().nx().px(10000)) != null;
if (!acquired) return;

try {
  processOrder(orderId);
} finally {
  // Unlock only if still owner (Lua compare-and-del)
  redis.eval(UNLOCK_LUA, 1, lockKey, owner);
}
Do not delete lock blindly; ownership check is mandatory.
4️⃣ Essential operational settingstext
- Eviction policy: allkeys-lru / volatile-ttl based on workload
- Persistence: RDB/AOF strategy by durability need
- Memory alarms: maxmemory + alerting
- Replication/failover: Sentinel or managed service
- Key naming: namespace prefixes for ownership clarity
📊

Why Redis vs only using relational DB

AspectOnly Relational DBRelational DB + Redis
Hot read latencyHigher under loadVery low for cached keys
Burst handlingDB can become bottleneckRedis absorbs read spikes
Ephemeral stateExtra schema/cleanup logicNatural with TTL keys
Atomic counters/rate controlPossible but heavierSimple atomic ops (INCR, Lua, transactions)
Cost/riskSimpler stackExtra component to operate correctly
🔀

Common Confusions Cleared Up

Cache vs source of truth

Redis is often best as acceleration/coordination layer. Your primary DB usually remains source of truth for durable business state.

Pub/Sub vs Streams

Pub/Sub is fire-and-forget and non-durable to offline consumers. Streams provide persisted event log with consumer groups and ack semantics.

Single-node speed vs distributed correctness

As soon as coordination/locking spans failures and partitions, correctness requires stronger patterns (timeouts, ownership, fencing, retries).

🧪

Variations / Implementations

1) Cache-aside pattern

Read path: check Redis first, fallback to DB on miss, then fill cache with TTL. This is the most common Redis use case.

2) Rate limiting (token/fixed window)

Use atomic increments + TTL or Lua scripts to enforce per-user/IP quotas efficiently.

3) Distributed lock (carefully)

Use SET key value NX PX ttl and verify ownership on unlock. Pair with fencing/timeout strategy for correctness-sensitive flows.

4) Realtime data structures

Sorted sets for leaderboards, hashes for profile/session maps, streams for consumer groups.

⚠️

Common Mistakes / Anti-Patterns

  • No TTL for cache keys (memory growth + stale data).
  • Cache stampede on hot-key misses without lock/coalescing.
  • Blind DEL during lock release (can unlock someone else).
  • Oversized values and unbounded key cardinality.
  • No monitoring of hit-rate, memory, evictions, and latency.
🎤

Interview Q&A

🧾

Quick Cheat Sheet

Most common useCache-aside with TTL.
Great atHot reads, counters, rate limits, ephemeral state.
Be careful withLock correctness, staleness, memory pressure.
Ops must-haveEviction policy + persistence + observability.
🔗

Related Topics