Everything you need to ace your Redis interview, from fundamentals to advanced topics.
Introduction
Preparing for a Redis interview? I've been there. Whether you're a senior engineer brushing up on fundamentals or someone new to Redis, I've compiled everything I wish I knew before my interviews.
This guide is based on questions I've actually faced in interviews and problems I've solved while building real systems. I've structured it in three levels: Fundamentals (must know), Intermediate (production ready), and Advanced (expert level). Each section builds on the previous one, so you can follow along at your own pace.
I'm sharing this because when I was preparing, I couldn't find one place that covered everything from basics to advanced topics in a way that made sense. Hopefully, this helps you avoid the same struggle.
LEVEL 1: FUNDAMENTALS (Must Know)
What is Redis?
Redis stands for Remote Dictionary Server. It's an in-memory data structure store that's incredibly fast:
- Key-Value store: Data stored as key-value pairs (dictionary-like structure)
- Multiple data types: Strings, Lists, Sets, Hashes, Sorted Sets (different types supported)
- Persistence options: Can save to disk (memory + disk options)
- Single-threaded: One command at a time (no race conditions)
Key Features:
- Speed: Microsecond latency (extremely fast - stored in memory)
- Atomic operations: Operations are all-or-nothing (no partial failures)
- Pub/Sub: Message broadcasting (publish events and subscribe to them)
- Transactions: Multiple commands as one unit (execute multiple commands together)
- Replication: Master-slave setup (backup copies for high availability)
Common Use Cases:
- Caching: Database query results, API responses (cache repeated data)
- Session storage: User sessions (store login info for fast access)
- Real-time analytics: Counters, leaderboards (live counts, rankings)
- Message queues: Task queues, job processing (background jobs)
- Rate limiting: API throttling (limit requests)
Interview Questions - Level 1
Q: What is Redis and why would you use it?
A: Redis is an in-memory data structure store (faster than milliseconds):
- Primary use: Caching layer between application and database (reduce DB load)
- Speed: 100K+ ops/sec possible (extremely fast - stored in memory)
- Data structures: Not just strings - lists, sets, hashes (supports complex data types)
- Persistence: Optional disk storage (memory + disk combination)
When to use Redis:
- Frequently accessed data (cache repeated queries)
- Session management (user login data)
- Real-time features (leaderboards, counters, notifications)
- Pub/Sub messaging (real-time events)
- Rate limiting (limit API calls)
Q: What are Redis data types?
A: Redis supports multiple data structures:
- String: Simple key-value (basic type - text, numbers, binary)
SET user:1:name "John"
GET user:1:name
INCR view_count
- List: Ordered collection (array-like - push/pop from both ends)
LPUSH tasks "task1"
RPUSH tasks "task2"
LPOP tasks
- Set: Unique unordered collection (no duplicates - unique values)
SADD tags "python" "redis"
SMEMBERS tags
SISMEMBER tags "python"
- Hash: Key-value pairs within a key (object-like - nested key-values)
HSET user:1 name "John" age 30
HGET user:1 name
HGETALL user:1
- Sorted Set: Set with scores (maintains ranking - perfect for leaderboards)
ZADD leaderboard 100 "player1"
ZADD leaderboard 200 "player2"
ZRANGE leaderboard 0 -1 WITHSCORES
Q: How does Redis achieve high performance?
A: This is a common question, and there are several factors that make Redis so fast:
In-memory storage: No disk I/O for reads (direct from RAM - microseconds). This is the biggest factor - reading from RAM is orders of magnitude faster than reading from disk.
Single-threaded: No context switching, no locks (simple execution model - automatic thread safety). This might sound counterintuitive, but avoiding locks and context switches actually makes Redis faster in many cases.
Optimized data structures: Efficient implementations (memory-optimized structures). Redis uses carefully designed data structures that are optimized for speed.
Event-driven: Non-blocking I/O (async operations - one thread handles many requests). Instead of blocking on I/O, Redis uses an event loop to handle thousands of connections efficiently.
Simple protocol: Low parsing overhead (RESP protocol - simple text-based). The protocol is simple to parse, which means less CPU time spent on parsing.
Q: What is the difference between Redis and Memcached?
A:
Redis:
- Multiple data types (strings, lists, sets, hashes, sorted sets)
- Persistence options (RDB snapshots, AOF logs)
- Replication and clustering (HA support - high availability)
- Pub/Sub messaging (real-time events)
- Transactions and Lua scripts (complex operations)
- Single-threaded (predictable performance)
Memcached:
- Only strings (simple key-value)
- No persistence (memory only - data lost on restart)
- Multi-threaded (better CPU utilization)
- Simpler, lighter (less features, less overhead)
- Better for simple caching (pure cache use case)
Use Redis when: Need data structures, persistence, pub/sub
Use Memcached when: Simple string caching, multi-core utilization
Q: Explain Redis persistence - RDB vs AOF.
A: This is one of those topics that trips people up. Redis has two ways to save data to disk, and they work differently:
RDB (Redis Database):
- Point-in-time snapshots (full backup at specific time). Think of it like taking a photo of your data at a specific moment.
- Compact binary format (compressed - storage efficient). The files are small and efficient.
- Faster restarts (loads single file). When Redis restarts, it just loads one file.
- Periodic saves:
SAVE 900 1(save if 1 change in 900 seconds). You can configure when snapshots happen. - Con: Can lose data between snapshots (data after last snapshot is lost). If Redis crashes between snapshots, you lose that data.
AOF (Append-Only File):
- Logs every write operation (records every command - like Git log). It's like a transaction log - every command gets written down.
- Better durability (minimum data loss - data up to latest). You're much less likely to lose data.
- Rewritable (can compact - remove duplicates). The file can get large, but Redis can compact it.
-
appendfsyncoptions:-
always: Every command (slow but safe). Every write goes to disk immediately. -
everysec: Every second (balanced - max 1 sec loss). A good middle ground. -
no: OS decides (fast but risky). Let the OS handle it, but you might lose more data.
-
- Con: Larger files, slower restarts. The files can get big, and restarting takes longer.
Best practice: Use both (RDB for backups, AOF for durability). This gives you the best of both worlds - fast backups with RDB and durability with AOF.
Q: What is Redis eviction policy?
A: When memory is full, Redis evicts keys based on policy (deletes keys when memory is full):
Eviction policies:
-
noeviction: Return errors (doesn't delete - returns error) -
allkeys-lru: Remove least recently used (delete old data from all keys - most common) -
allkeys-lfu: Remove least frequently used (delete less frequently used data) -
volatile-lru: LRU among keys with TTL (from keys with expire set) -
volatile-lfu: LFU among keys with TTL -
volatile-random: Random among keys with TTL -
volatile-ttl: Remove keys with shortest TTL (keys expiring soon first) -
allkeys-random: Random removal
Common choice: allkeys-lru for cache (automatically clears least used data)
Q: How do you set expiration on keys?
A: Multiple commands for TTL (time to live):
SET key value EX 300 # Expire in 300 seconds
SET key value PX 300000 # Expire in 300000 milliseconds
SETEX key 300 value # Set with expiration
EXPIRE key 300 # Set expiration on existing key
TTL key # Check remaining time
PERSIST key # Remove expiration
Use cases:
- Session data (auto logout after inactivity)
- Cache entries (auto refresh stale data)
- Rate limiting (reset counters periodically)
- OTP codes (expire after time)
LEVEL 2: INTERMEDIATE (Production Ready)
Transactions:
- MULTI/EXEC: Group commands atomically (execute multiple commands together - all or nothing)
- WATCH: Optimistic locking (check then update - avoid race condition)
- DISCARD: Cancel transaction (like rollback)
Pub/Sub:
- PUBLISH/SUBSCRIBE: Message broadcasting (publish events and subscribe)
- PSUBSCRIBE: Pattern-based subscriptions (wildcard patterns)
- Channels: Topic-based messaging (like topics - specific channels)
Pipelining:
- Batch commands: Reduce network round-trips (send multiple commands together)
- Performance: Massive throughput increase (reduces RTT overhead)
Lua Scripts:
- EVAL: Execute Lua code in Redis (server-side logic)
- Atomic execution: Script runs atomically (no interruption in middle)
- EVALSHA: Cached scripts (call using script hash - efficient)
Replication:
- Master-Slave: Read replicas (write to master, read from slaves)
- Asynchronous: Eventual consistency (not immediate sync - slight delay)
- Replication lag: Slaves may be behind (monitor this)
- Read scaling: Distribute reads across slaves
Redis Sentinel:
- High availability: Automatic failover (detects master failure)
- Monitoring: Watches master and slaves (continuous monitoring)
- Automatic promotion: Promotes slave to master (when master fails)
- Quorum: Requires multiple sentinels (consensus needed)
Redis Cluster:
- Sharding: Data distributed across nodes (horizontal scaling)
- Hash slots: 16384 slots distributed (keys mapped to slots)
- Automatic failover: Node failure handling (self-healing)
- No single point of failure: Distributed architecture
Interview Questions - Level 2
Q: Explain Redis transactions with MULTI/EXEC.
A: Transactions execute multiple commands atomically (multiple commands together - can't be interrupted):
MULTI # Start transaction
SET balance:1 100 # Queue command
DECR balance:1 # Queue command
INCR balance:2 # Queue command
EXEC # Execute all
Key points:
- Commands are queued, not executed immediately (only execute after EXEC)
- All-or-nothing execution (all run or all fail)
- Other clients blocked during execution (transaction runs, others wait)
With WATCH (Optimistic locking):
WATCH balance:1 # Monitor key
val = GET balance:1
# ... check value ...
MULTI
SET balance:1 new_val
EXEC # Fails if balance:1 changed
Use cases:
- Atomic operations (multiple commands must succeed together)
- Conditional updates (check then set)
- Financial transactions (debit/credit together)
Q: What is Redis pipelining and when to use it?
A: Pipelining sends multiple commands without waiting for responses (send batch - saves RTT):
Without pipelining:
Client: GET key1
Server: value1
Client: GET key2
Server: value2
Total: 2 round trips (two network travels - slow)
With pipelining:
Client: GET key1; GET key2; GET key3
Server: value1; value2; value3
Total: 1 round trip (one send - fast)
Example (Python):
pipe = redis.pipeline()
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.get('key1')
results = pipe.execute() # All at once
Use when:
- Multiple independent operations (related commands)
- Network latency is bottleneck (high RTT)
- Bulk operations (many commands at once)
Performance: 10x-100x faster than individual commands (eliminates RTT overhead)
Q: How does Pub/Sub work in Redis?
A: Pub/Sub enables message broadcasting (publishers send, subscribers receive):
Publisher:
PUBLISH notifications "New user signup"
PUBLISH logs:error "Database connection failed"
Subscriber:
SUBSCRIBE notifications logs:error # Waits for messages
Pattern matching:
PSUBSCRIBE logs:* # Pattern matching (all logs:* channels)
Characteristics:
- Fire-and-forget (messages not stored - delivered then forgotten)
- No message queue (offline subscribers miss messages)
- Multiple subscribers (all receive same message)
- Real-time delivery (instant - no delay)
Use cases:
- Real-time notifications (chat, alerts)
- Event broadcasting (system events)
- Cache invalidation (distributed cache update)
- Microservices communication (event-driven)
Q: Explain Redis Lua scripting.
A: Lua scripts run server-side atomically (execute on server - atomic + fast):
EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue
Benefits:
- Atomic execution: No interruptions (no commands in middle)
- Reduced network: Complex logic in one call (avoid multiple round trips)
- Consistent: Logic guaranteed same (client logic doesn't vary)
Example - Rate limiting:
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call('GET', key) or "0")
if current < limit then
redis.call('INCR', key)
redis.call('EXPIRE', key, 60)
return 1
else
return 0
end
Use cases:
- Atomic operations (complex multi-step operations)
- Rate limiting (check + increment atomically)
- Conditional updates (check-then-set patterns)
- Complex calculations (multiple operations together)
EVALSHA for efficiency:
SCRIPT LOAD "return redis.call('GET', KEYS[1])"
# Returns: sha1_hash
EVALSHA sha1_hash 1 mykey # Use hash instead of script
Q: How does Redis replication work?
A: Master-slave replication for high availability (master copy to slaves - backup + read scaling):
Setup:
# On slave
REPLICAOF master-host 6379
How it works:
- Slave connects to master (connection established)
- Master sends RDB snapshot (initial data copy)
- Master sends command stream (continuous updates)
- Asynchronous replication (slaves lag slightly - eventual consistency)
Benefits:
- Read scaling: Slaves handle reads (read requests can go to slaves)
- High availability: Failover to slave (master down, promote slave)
- Data safety: Multiple copies (backups - less data loss)
Limitations:
- Writes only to master: Slaves read-only (write only to master)
- Replication lag: Slaves slightly behind (few milliseconds delay)
- Manual failover: Need Sentinel for automatic (Redis Sentinel needed for auto failover)
Monitoring replication:
INFO replication # Check replication status
# master_repl_offset - master's offset
# slave_repl_offset - slave's offset
# Difference = lag
Q: What is Redis Sentinel?
A: Sentinel provides high availability and monitoring (automatic failover - master down, promote slave):
Features:
- Monitoring: Check master/slave health (continuous health check)
- Notification: Alert on failures (notify on problems)
- Automatic failover: Promote slave to master (automatic master change)
- Configuration provider: Clients get current master (clients get current master info)
Architecture:
- Multiple Sentinel instances (quorum for decisions - majority vote)
- Monitors Redis instances (all masters and slaves)
- Consensus-based failover (majority agree before failover)
Setup:
# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000
Client usage:
from redis.sentinel import Sentinel
sentinel = Sentinel([
('sentinel1', 26379),
('sentinel2', 26379),
('sentinel3', 26379)
])
# Always gets current master
master = sentinel.master_for('mymaster')
# Read from slaves
slave = sentinel.slave_for('mymaster')
Q: How do you implement caching patterns with Redis?
A: Common caching strategies:
1. Cache-Aside (Lazy Loading):
def get_user(user_id):
# Try cache first
user = redis.get(f"user:{user_id}")
if user:
return user
# Cache miss - fetch from DB
user = db.query(f"SELECT * FROM users WHERE id={user_id}")
# Store in cache
redis.setex(f"user:{user_id}", 3600, user)
return user
Pros:
- Only cache what's needed (cache used data only)
- Simple to implement
Cons:
- Cache miss penalty (first time is slow - DB query)
- Potential stale data (if updated elsewhere)
2. Write-Through:
def update_user(user_id, data):
# Update DB
db.update(f"UPDATE users SET ... WHERE id={user_id}")
# Update cache
redis.setex(f"user:{user_id}", 3600, data)
Pros:
- Cache always fresh (consistent data)
- No stale data issues
Cons:
- Write latency (need to update both - slower)
- More writes (both DB and cache)
3. Write-Behind (Write-Back):
def update_user(user_id, data):
# Update cache immediately
redis.setex(f"user:{user_id}", 3600, data)
# Queue DB write asynchronously
queue.push({'type': 'user_update', 'id': user_id, 'data': data})
Pros:
- Fast writes (immediate response)
- Better write performance
Cons:
- Potential data loss (if crash before DB write)
- More complex (need async queue)
- Eventual consistency (DB may lag)
4. Refresh-Ahead:
def get_user(user_id):
user = redis.get(f"user:{user_id}")
ttl = redis.ttl(f"user:{user_id}")
# Refresh if expiring soon
if ttl < 300: # Less than 5 minutes left
# Refresh in background
async_refresh(user_id)
return user
Pros:
- Always fresh (proactive refresh)
- No cache miss penalty
Cons:
- More complex (background refresh logic)
- May refresh unnecessarily
Q: How do you handle cache invalidation?
A: Multiple strategies:
1. TTL-based:
redis.setex("key", 3600, value) # Expires in 1 hour
- Simple, automatic (no manual intervention)
- May serve stale data (until expiration)
2. Event-based:
def update_user(user_id, data):
db.update(user_id, data)
redis.delete(f"user:{user_id}") # Invalidate cache
- Fresh data guaranteed (cache cleared on update)
- Requires application logic (explicit handling)
3. Version-based:
version = redis.incr("user:version")
redis.set(f"user:{user_id}:v{version}", data)
- Multiple versions coexist (old + new both exist)
- Complex to manage (version tracking)
4. Pub/Sub broadcast:
redis.publish("cache:invalidate", f"user:{user_id}")
- Distributed invalidation (all servers notified)
- All instances update (cluster-wide consistency)
LEVEL 3: ADVANCED (Expert Level)
Q: Explain Redis Cluster architecture.
A: Redis Cluster provides sharding and HA (data distributed for high availability):
Architecture:
- Hash slots: 16384 slots (keys distributed based on hash)
- Nodes: Minimum 3 masters (data split across masters)
- Replication: Each master has slaves (backup + failover)
- No proxy: Clients connect directly (smart clients route to correct node)
Key distribution:
HASH_SLOT = CRC16(key) mod 16384
Keys with same hash tag go to same node:
{user:1}:profile
{user:1}:settings
# Both go to same node (hash tag: user:1)
Failover:
- Slave detects master failure (health check continuous)
- Majority of masters vote (quorum required)
- Promote slave to master (automatic promotion)
Limitations:
- No multi-key operations across slots: Transactions only work within single slot
- Resharding is manual: Moving slots requires manual intervention
- Client must be cluster-aware: Must calculate CRC16 and connect to correct node
Setup:
# redis-cluster.conf
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
Client usage:
from redis.cluster import RedisCluster
rc = RedisCluster(
startup_nodes=[
{"host": "127.0.0.1", "port": "7000"},
{"host": "127.0.0.1", "port": "7001"},
],
decode_responses=True
)
Q: How do you monitor and troubleshoot Redis?
A: Multiple monitoring approaches:
1. INFO command:
INFO server # Server info
INFO stats # Statistics
INFO memory # Memory usage
INFO replication # Replication status
2. SLOWLOG:
SLOWLOG GET 10 # Last 10 slow commands
CONFIG SET slowlog-log-slower-than 10000 # Log commands > 10ms
3. Key metrics to monitor:
-
Latency:
redis-cli --latency(response time) -
Memory:
used_memory,used_memory_peak(RAM usage) -
Hit rate:
keyspace_hits / (keyspace_hits + keyspace_misses)(cache effectiveness) -
Evictions:
evicted_keys(memory pressure indicator) -
Connections:
connected_clients(client connections) -
Replication lag:
master_repl_offset - slave_repl_offset(slave delay)
4. Tools:
- Redis Exporter + Prometheus + Grafana (metrics visualization)
- RedisInsight (GUI tool - real-time monitoring)
- redis-stat (command-line tool)
Common issues:
- High latency: Slow commands, blocking operations, swap
- Memory issues: No eviction policy, memory leaks, large keys
- Connection spikes: Connection pool exhaustion
- Replication lag: Network issues, slow queries
Q: What are Redis memory optimization techniques?
A: Multiple strategies to reduce memory:
1. Choose right data structures:
# Instead of multiple keys
SET user:1:name "John"
SET user:1:email "john@example.com"
# Use hash (more efficient - single key)
HSET user:1 name "John" email "john@example.com"
2. Use hash encoding:
CONFIG SET hash-max-ziplist-entries 512
CONFIG SET hash-max-ziplist-value 64
Small hashes stored efficiently (ziplist - memory compact)
3. Set TTL on everything:
SETEX key 3600 value # Auto cleanup
4. Use compression:
- Compress values before storing (client-side compression)
- Trade CPU for memory (need to decompress when using)
5. Avoid large keys:
- Split large values into smaller chunks (like pagination)
- Use sorted sets instead of large lists
6. Monitor memory:
MEMORY USAGE key # Memory used by key
MEMORY STATS # Memory statistics
Q: How do you implement rate limiting with Redis?
A: Multiple approaches:
1. Fixed Window:
def is_allowed(user_id, limit=10):
key = f"rate:{user_id}:{time.time() // 60}" # Per minute
count = redis.incr(key)
redis.expire(key, 60)
return count <= limit
- Simple, but edge case: burst at window boundary
2. Sliding Window (Token Bucket):
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
local count = redis.call('ZCARD', key)
if count < limit then
redis.call('ZADD', key, now, now)
redis.call('EXPIRE', key, window)
return 1
else
return 0
end
- Accurate, smooth limiting (requests spread evenly)
3. Leaky Bucket:
def is_allowed(user_id, limit=10, window=60):
key = f"rate:{user_id}"
pipe = redis.pipeline()
now = time.time()
# Remove old entries
pipe.zremrangebyscore(key, 0, now - window)
# Count remaining
pipe.zcard(key)
# Add current request
pipe.zadd(key, {now: now})
# Set expiration
pipe.expire(key, window)
results = pipe.execute()
return results[1] < limit
Q: How do you handle Redis failover in production?
A: Multi-layered approach:
1. Redis Sentinel Setup:
# 3+ Sentinel instances for quorum
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000
2. Client configuration:
from redis.sentinel import Sentinel
sentinel = Sentinel([
('sentinel1', 26379),
('sentinel2', 26379),
('sentinel3', 26379)
], socket_timeout=0.1)
# Always gets current master
master = sentinel.master_for('mymaster', socket_timeout=0.1)
# Read from slaves
slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
3. Application resilience:
- Connection pooling (reuse connections)
- Retry logic with exponential backoff (retry on failures)
- Circuit breaker pattern (stop on repeated failures)
- Graceful degradation (continue without cache if Redis is down)
4. Monitoring:
- Continuous health checks (track uptime)
- Alert on failover events (notifications)
- Track replication lag (slaves catching up)
- Monitor client connections (connection spikes)
Q: What are common Redis anti-patterns?
A:
- Large keys: Storing huge values (>1MB) blocks Redis (split into smaller chunks)
- KEYS command in production: Scans all keys (use SCAN instead - non-blocking)
- Unbounded lists: Lists growing infinitely (use LTRIM to limit)
- Hot keys: Single key accessed by everyone (shard or replicate)
- No expiration: Keys never expire (memory fills up - set TTL)
- Synchronous operations: Blocking commands (use async, pipelining)
- Connection per request: Expensive (use connection pool)
- No monitoring: Can't debug issues (metrics mandatory)
REAL INTERVIEW SCENARIOS
Challenge 1: Implement distributed lock
import redis
import uuid
import time
class RedisLock:
def __init__(self, redis_client, key, timeout=10):
self.redis = redis_client
self.key = f"lock:{key}"
self.timeout = timeout
self.identifier = str(uuid.uuid4())
def acquire(self):
end_time = time.time() + self.timeout
while time.time() < end_time:
if self.redis.set(self.key, self.identifier, nx=True, ex=self.timeout):
return True
time.sleep(0.001)
return False
def release(self):
# Lua script for atomic check-and-delete
lua_script = """
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
"""
self.redis.eval(lua_script, 1, self.key, self.identifier)
# Usage
lock = RedisLock(redis_client, "resource:123")
if lock.acquire():
try:
# Critical section
process_resource()
finally:
lock.release()
Challenge 2: Leaderboard with Redis Sorted Set
class Leaderboard:
def __init__(self, redis_client, name):
self.redis = redis_client
self.key = f"leaderboard:{name}"
def add_score(self, player, score):
self.redis.zadd(self.key, {player: score})
def increment_score(self, player, amount):
self.redis.zincrby(self.key, amount, player)
def get_rank(self, player):
# Rank (0-based, descending)
rank = self.redis.zrevrank(self.key, player)
return rank + 1 if rank is not None else None
def get_top(self, n=10):
return self.redis.zrevrange(self.key, 0, n-1, withscores=True)
def get_around(self, player, radius=2):
rank = self.redis.zrevrank(self.key, player)
if rank is None:
return []
start = max(0, rank - radius)
end = rank + radius
return self.redis.zrevrange(self.key, start, end, withscores=True)
Challenge 3: Session management
import json
from datetime import timedelta
class SessionManager:
def __init__(self, redis_client, timeout=3600):
self.redis = redis_client
self.timeout = timeout
def create_session(self, session_id, user_data):
key = f"session:{session_id}"
self.redis.setex(key, self.timeout, json.dumps(user_data))
def get_session(self, session_id):
key = f"session:{session_id}"
data = self.redis.get(key)
if data:
# Refresh TTL on access
self.redis.expire(key, self.timeout)
return json.loads(data)
return None
def update_session(self, session_id, user_data):
key = f"session:{session_id}"
if self.redis.exists(key):
self.redis.setex(key, self.timeout, json.dumps(user_data))
return True
return False
def delete_session(self, session_id):
key = f"session:{session_id}"
self.redis.delete(key)
QUESTIONS TO ASK THE INTERVIEWER
Technical:
- "What's your Redis deployment setup? Standalone, Sentinel, or Cluster?"
- "How do you handle cache invalidation strategies?"
- "What's your approach to Redis persistence (RDB/AOF)?"
- "How do you monitor Redis performance and health?"
- "What's your Redis version and upgrade strategy?"
Operational:
- "How do you handle Redis failover and disaster recovery?"
- "What's your strategy for memory management and eviction?"
- "How do you handle Redis backups and restore procedures?"
- "What's the typical Redis workload (read/write ratio)?"
- "How do you ensure Redis security (auth, encryption)?"
QUICK PREP CHECKLIST
Day 1-2: Basics
- [ ] Data types and commands
- [ ] Persistence (RDB/AOF)
- [ ] Expiration and eviction
- [ ] Build simple cache
Day 3-4: Intermediate
- [ ] Transactions and pipelining
- [ ] Pub/Sub messaging
- [ ] Lua scripting
- [ ] Implement rate limiter
Day 5-6: Advanced
- [ ] Replication and Sentinel
- [ ] Redis Cluster
- [ ] Performance tuning
- [ ] Build distributed lock
Day 7: Review
- [ ] Review concepts
- [ ] Practice scenarios
- [ ] Prepare questions
Conclusion
Redis is a powerful tool that goes far beyond simple caching. Understanding its data structures, persistence options, and advanced features will help you build scalable systems and ace your interviews.
The key is to practice. Set up a local Redis instance, try the examples in this guide, and build something with it. The more hands-on experience you have, the more confident you'll be in interviews and production environments.
Good luck with your Redis interviews!
Recommended Resources
Official Documentation
- Redis Official Documentation - Complete reference
- Redis Commands Reference - All commands with examples
- Redis University - Free courses and certifications
Books
- "Redis in Action" by Josiah Carlson - Comprehensive guide with real-world examples
- "The Little Redis Book" by Karl Seguin - Quick introduction to Redis concepts
Practice
- Set up a local Redis instance and experiment with commands
- Build a caching layer for your application
- Implement rate limiting, session management, and leaderboards
- Try the coding challenges in this guide
Related Articles
- Understanding Connections and Threads in Backend Services - Complete guide on how single-threaded systems handle high concurrency
- 6 Common Redis and Kafka Challenges I Faced and How I Solved Them - Real-world challenges and solutions from my EventStreamMonitor project
Top comments (0)