Loading content...
If SAP HANA represents enterprise-grade complexity, Redis represents the opposite philosophy: radical simplicity achieving extraordinary performance. Redis (Remote Dictionary Server) is an in-memory data structure store that has become nearly ubiquitous in modern software architecture.
Created by Salvatore Sanfilippo in 2009, Redis was designed with a single-minded focus: make the simplest possible thing as fast as possible. This philosophy—combined with its rich data structure support and developer-friendly API—has made Redis the default choice for caching, session storage, real-time analytics, and countless other use cases.
With over 50,000 GitHub stars, deployment in virtually every major technology company, and serving as the "secret weapon" behind many high-performance systems, Redis deserves deep understanding.
By the end of this page, you will understand: Redis's design philosophy and architecture, its rich data structure ecosystem, performance characteristics and deployment patterns, persistence options for durability, and when Redis is the optimal choice for your system.
Redis's power comes from disciplined simplicity. Understanding its design principles explains why it achieves such remarkable performance.
Core Design Principles
1. Single-Threaded Event Loop
Redis processes all commands on a single thread using an event-driven, non-blocking I/O model. This might seem counterintuitive for performance, but it provides crucial advantages:
Modern Redis (6.0+) uses I/O threads for network handling, but command execution remains single-threaded.
2. Memory-First Design
Unlike databases that "also support" in-memory tables, Redis is designed from the ground up for RAM:
3. Rich Data Structures as First-Class Citizens
Redis isn't just a key-value store—it's a data structure server. Each data structure is carefully implemented with optimal algorithms:
4. Minimizing Network Round-Trips
Redis commands are designed to do meaningful work in a single round-trip. Instead of fetching data, modifying it client-side, and writing back, Redis provides atomic operations:
Anti-Pattern: Multiple Round-Trips─────────────────────────────────────────────────────────────── Client Redis │ │ │──── GET counter ──────────────────►│ │◄─── "42" ─────────────────────────│ │ │ │ (client: value = 42 + 1) │ │ │ │──── SET counter 43 ───────────────►│ │◄─── OK ───────────────────────────│ │ │ │ 2 round-trips, race conditions possible! │ Redis Pattern: Single Atomic Command─────────────────────────────────────────────────────────────── Client Redis │ │ │──── INCR counter ─────────────────►│ │◄─── 43 ───────────────────────────│ │ │ │ 1 round-trip, atomic, no race conditions!When multiple independent operations are needed, Redis pipelining sends them all without waiting for individual responses. A 100-command pipeline completes in almost the same time as a single command, amortizing network latency across all operations.
Redis's rich data structure support distinguishes it from simple caching solutions. Each structure is optimized for specific access patterns.
Strings
The most basic type, but surprisingly powerful. Strings can hold any binary data up to 512MB.
Common Uses: Caching, counters, locks, rate limiters, bitmap operations
Redis String Operations # Basic operationsSET user:1000:name "Alice" # O(1)GET user:1000:name # O(1) → "Alice" # Atomic numeric operationsSET page:views 0INCR page:views # O(1) → 1INCRBY page:views 100 # O(1) → 101 # Atomic string operations APPEND user:1000:log "entry1," # O(1) amortizedSTRLEN user:1000:log # O(1) → 7 # Bitmap operations (strings as bit arrays)SETBIT users:active:2024-01-15 1000 1 # User 1000 was activeSETBIT users:active:2024-01-15 1001 1 # User 1001 was activeBITCOUNT users:active:2024-01-15 # Count active users # ExpirationSET session:abc123 "user_data" EX 3600 # Expires in 1 hourLists
Doubly-linked lists optimized for operations at both ends. Ideal for queues, timelines, and activity feeds.
Implementation: Quicklist (linked list of ziplist nodes) Complexity: O(1) push/pop at ends, O(N) access by index
Redis List Operations # Queue pattern (FIFO)LPUSH queue:tasks "task1" # Push leftLPUSH queue:tasks "task2"RPOP queue:tasks # Pop right → "task1" # Stack pattern (LIFO)LPUSH stack:undo "action1"LPUSH stack:undo "action2" LPOP stack:undo # Pop left → "action2" # Blocking operations (ideal for worker queues)BRPOP queue:tasks 30 # Block up to 30s for task # Timeline/feed patternLPUSH timeline:user:1000 "post:5001"LPUSH timeline:user:1000 "post:5002"LRANGE timeline:user:1000 0 19 # Get latest 20 posts # Trim to bounded listLTRIM timeline:user:1000 0 999 # Keep only 1000 most recentSets
Unordered collections of unique strings. Excellent for membership testing, tagging, and set operations.
Implementation: Intset for small integer sets, hashtable otherwise Complexity: O(1) add/remove/membership test
Redis Set Operations # Tag systemSADD article:1001:tags "redis" "database" "nosql"SMEMBERS article:1001:tags # → ["redis", "database", "nosql"]SISMEMBER article:1001:tags "redis" # O(1) → 1 (true) # Find articles with common tags (intersection)SADD article:1002:tags "redis" "caching"SINTER article:1001:tags article:1002:tags # → ["redis"] # Online users trackingSADD online:users "user:1000"SADD online:users "user:1001"SCARD online:users # Count: 2SREM online:users "user:1000" # User went offline # Random samplingSADD lottery:participants "user:1" "user:2" "user:3" "user:4"SRANDMEMBER lottery:participants 2 # Random 2 winnersSorted Sets (ZSets)
Unique strings ordered by floating-point score. Perhaps Redis's most powerful structure—powers leaderboards, rate limiters, time-based indexes, and priority queues.
Implementation: Skip list + hashtable hybrid Complexity: O(log N) add/remove, O(log N + M) range queries
Redis Sorted Set Operations # LeaderboardZADD leaderboard 1000 "player:alice"ZADD leaderboard 1500 "player:bob"ZADD leaderboard 1200 "player:charlie" ZREVRANGE leaderboard 0 2 WITHSCORES # Top 3 (descending)# → ["player:bob", 1500, "player:charlie", 1200, "player:alice", 1000] ZRANK leaderboard "player:bob" # Rank (0-indexed) → 0ZINCRBY leaderboard 600 "player:alice" # Alice scores 600 more # Time-based indexes (score = timestamp)ZADD events:user:1000 1705276800 "login"ZADD events:user:1000 1705277100 "page_view"ZADD events:user:1000 1705278000 "purchase" # Get events in time rangeZRANGEBYSCORE events:user:1000 1705276000 1705278000 # Sliding window rate limiter# Score = timestamp, member = unique request IDZADD rate:api:user:1000 1705277100.123 "req:abc123"ZREMRANGEBYSCORE rate:api:user:1000 0 (NOW - 60) # Remove oldZCARD rate:api:user:1000 # Count requests in last 60 secondsHashes
Maps of field-value pairs. Perfect for representing objects without serialization overhead.
Implementation: Ziplist for small hashes, hashtable otherwise Complexity: O(1) for individual field operations
Redis Hash Operations # User profile as hashHSET user:1000 name "Alice" email "alice@example.com" age 30HGET user:1000 name # → "Alice"HGETALL user:1000 # → {name: "Alice", email: "...", age: "30"} # Partial updates (vs full object replacement)HINCRBY user:1000 age 1 # Birthday! Atomic increment # Multi-get for performanceHMGET user:1000 name email # → ["Alice", "alice@example.com"] # Check field existenceHEXISTS user:1000 premium # → 0 (false) # Efficient object storage# Instead of: SET user:1000 '{"name":"Alice","email":"...","age":30}'# Use hash: individual fields updateable, no serialization neededRedis also supports: HyperLogLog (probabilistic cardinality counting), Streams (append-only log with consumer groups), Geospatial indexes (location-based queries), and Bitmaps/Bitfields (compact bit manipulation). These specialized structures enable sophisticated use cases with minimal code.
Redis is engineered for extreme performance. Understanding its performance characteristics helps you design systems that fully leverage its capabilities.
Latency
Redis operations typically complete in sub-millisecond time. On local connections, average latency is often under 100 microseconds.
| Operation Type | Complexity | Typical Latency |
|---|---|---|
| GET/SET (simple key) | O(1) | 30-100 μs |
| INCR/DECR | O(1) | 30-100 μs |
| LPUSH/RPOP | O(1) | 30-100 μs |
| SADD/SISMEMBER | O(1) | 30-100 μs |
| ZADD/ZRANK | O(log N) | 50-200 μs |
| ZRANGE (100 elements) | O(log N + M) | 100-300 μs |
| Pipeline (100 commands) | O(k) | 200-500 μs total |
Throughput
A single Redis instance can handle extraordinary throughput:
Why So Fast?
Redis's performance comes from multiple design decisions working together:
Redis Performance Factors ┌─────────────────────────────────────────────────────────────────┐│ TIME BREAKDOWN: GET Command │├─────────────────────────────────────────────────────────────────┤│ ││ Network receive: ~10 μs ▓▓ ││ Protocol parse: ~2 μs ▏ ││ Command lookup: ~1 μs ▏ ││ Key hash: ~1 μs ▏ ││ Hashtable lookup: ~5 μs ▓ ││ Serialize response: ~2 μs ▏ ││ Network send: ~10 μs ▓▓ ││ ───────────────────────────── ││ Total: ~31 μs ││ ││ Notes: ││ • Network is largest component (local connection) ││ • Remote network: add ~200-500 μs ││ • Actual data access: <10 μs ││ │└─────────────────────────────────────────────────────────────────┘ PIPELINING ADVANTAGE:┌───────────────────────────────────────────────────────────┐│ Without Pipeline: ││ 100 commands × 31 μs = 3,100 μs (3.1 ms) ││ ││ With Pipeline: ││ 1 batch × (20 μs network + 100 × 11 μs processing) ││ = 1,120 μs (1.1 ms) ││ ││ Speedup: ~3x for local, ~50x+ for remote connections │└───────────────────────────────────────────────────────────┘Commands like KEYS *, SMEMBERS on huge sets, or SORT on large lists block the entire Redis server. Use SCAN for iteration, limit result sizes, and monitor slow queries with SLOWLOG. A single slow command can spike latency for all clients.
Despite being an in-memory database, Redis provides multiple persistence options ranging from no persistence (pure cache) to synchronous durability.
RDB (Redis Database Backup)
Point-in-time snapshots of the entire dataset.
Mechanism:
Advantages:
Disadvantages:
AOF (Append-Only File)
Logging every write command to disk.
Mechanism:
Advantages:
Disadvantages:
Redis Persistence Configuration # ═══════════════════════════════════════════════════════════════# NO PERSISTENCE (Pure Cache)# ═══════════════════════════════════════════════════════════════# Fastest performance, data lost on restartsave ""appendonly no # ═══════════════════════════════════════════════════════════════# RDB ONLY (Point-in-Time Snapshots)# ═══════════════════════════════════════════════════════════════# Snapshot every 5 min if at least 100 writessave 300 100# Snapshot every 1 min if at least 10,000 writessave 60 10000appendonly no # Data loss window: up to 5 minutes # ═══════════════════════════════════════════════════════════════# AOF ONLY (Append-Only File)# ═══════════════════════════════════════════════════════════════save ""appendonly yesappendfsync everysec # Sync every second (recommended)# appendfsync always # Sync every write (slow but safe) # Data loss window: ~1 second (or none with fsync always) # ═══════════════════════════════════════════════════════════════# RDB + AOF (Recommended for Production)# ═══════════════════════════════════════════════════════════════save 300 100appendonly yesappendfsync everysecaof-use-rdb-preamble yes # Faster AOF loading (Redis 4.0+) # Fast restart via RDB, AOF for recent changes| Aspect | No Persistence | RDB Only | AOF Only | RDB + AOF |
|---|---|---|---|---|
| Data Durability | None | Minutes | Seconds | Seconds |
| Write Performance | Maximum | High | Medium-High | Medium-High |
| Restart Speed | Instant (empty) | Fast | Slow | Fast |
| Disk Usage | None | Low | Medium-High | Medium |
| Use Case | Pure cache | Tolerant apps | Low data loss | Production |
Redis 7.0 improved the RDB+AOF combination with a feature called 'multi-part AOF'. This allows more granular management of AOF files and improves both reliability and restart performance. Always use the latest stable Redis version for production workloads.
Single-instance Redis provides extreme performance but is limited by single-server memory and represents a single point of failure. Redis provides multiple approaches to scaling and high availability.
Redis Sentinel
High availability solution for non-clustered Redis:
Best for: High availability without sharding requirements
Redis Sentinel Topology ┌─────────────────────────────────────────────────────────────────┐│ APPLICATION LAYER ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ Client │ │ Client │ │ Client │ ││ └────┬────┘ └────┬────┘ └────┬────┘ ││ │ │ │ ││ └────────────┼────────────┘ ││ │ ││ ▼ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ SENTINEL LAYER │ ││ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ ││ │ │Sentinel1│ │Sentinel2│ │Sentinel3│ │ ││ │ └────┬────┘ └────┬────┘ └────┬────┘ │ ││ │ │ │ │ │ ││ │ └──────────────┼──────────────┘ │ ││ │ │ Quorum-based │ ││ │ │ failover decision │ ││ └───────────────────────┼─────────────────────────────────┘ ││ │ ││ ▼ ││ ┌───────────────────────────────────────────────────────────┐ ││ │ REDIS LAYER │ ││ │ │ ││ │ ┌─────────────┐ │ ││ │ │ MASTER │ ◄─── All writes │ ││ │ │ (Node 1) │ │ ││ │ └──────┬──────┘ │ ││ │ │ Async replication │ ││ │ ┌─────┴─────┐ │ ││ │ ▼ ▼ │ ││ │ ┌─────────┐ ┌─────────┐ │ ││ │ │ REPLICA │ │ REPLICA │ ◄─── Reads (optional) │ ││ │ │(Node 2) │ │(Node 3) │ │ ││ │ └─────────┘ └─────────┘ │ ││ └───────────────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────────┘Redis Cluster
Built-in sharding with automatic failover:
Best for: Datasets larger than single-server memory, high throughput requirements
Redis Cluster Topology (6-node example) Hash Slots: 0 ────────────────────────────────────── 16383 ┌─────────────────────────────────────────────────────────────────┐│ REDIS CLUSTER ││ ││ Slots 0-5460 Slots 5461-10922 Slots 10923-16383 ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ MASTER-1 │ │ MASTER-2 │ │ MASTER-3 │ ││ │ (Node A) │ │ (Node B) │ │ (Node C) │ ││ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ ││ │ │ │ ││ │ Replication │ Replication │ Replication ││ ▼ ▼ ▼ ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ REPLICA-1 │ │ REPLICA-2 │ │ REPLICA-3 │ ││ │ (Node D) │ │ (Node E) │ │ (Node F) │ ││ └─────────────┘ └─────────────┘ └─────────────┘ ││ ││ Key routing: HASH_SLOT = CRC16(key) mod 16384 ││ ││ Example: "user:1000" → CRC16 → slot 7562 → MASTER-2 ││ │└─────────────────────────────────────────────────────────────────┘ Cluster Operations:• Client libraries handle automatic routing• MOVED/ASK redirects for slot migration• Cross-slot operations limited (use hash tags)• Resharding possible without downtimeRedis Cluster cannot atomically operate on keys in different slots. Operations like MGET across cluster will fail unless all keys hash to the same slot. Use hash tags {user:1000}:name and {user:1000}:email to force keys to the same slot when atomic cross-key operations are needed.
Redis's combination of speed, data structures, and simplicity makes it ideal for numerous application patterns.
1. Caching
The most common Redis use case. Cache database query results, API responses, or computed values:
Cache-aside pattern:
1. Check Redis for cached value
2. If miss, query primary database
3. Store result in Redis with expiration
4. Return value
Why Redis excels: TTL support, LRU eviction, sub-millisecond access, atomic operations for cache stampede prevention.
2. Session Storage
Store user sessions with automatic expiration:
Why Redis excels: Fast access for every authenticated request, built-in expiration, horizontal scaling with Cluster.
3. Rate Limiting
Sliding window rate limiting using sorted sets:
1. Add current request to sorted set (score = timestamp)
2. Remove entries older than window
3. Count remaining entries
4. Allow/deny based on count vs. limit
Why Redis excels: Atomic operations, sorted sets with range operations, microsecond execution.
4. Real-Time Leaderboards
Sorted sets are purpose-built for leaderboards:
Why Redis excels: Updates and queries both sub-millisecond, even at millions of entries.
5. Message Queues
Lightweight queuing with lists:
For more advanced messaging, Redis Streams provide consumer groups, acknowledgment, and message history.
6. Real-Time Analytics
| Use Case | Primary Data Structure | Key Commands |
|---|---|---|
| Caching | Strings, Hashes | GET, SET, HGET, HSET, EXPIRE |
| Sessions | Hashes | HSET, HGETALL, EXPIRE |
| Rate Limiting | Sorted Sets | ZADD, ZREMRANGEBYSCORE, ZCARD |
| Leaderboards | Sorted Sets | ZADD, ZREVRANGE, ZRANK |
| Queues | Lists, Streams | LPUSH, BRPOP, XADD, XREAD |
| Counting | Strings, HyperLogLog | INCR, PFADD, PFCOUNT |
| Pub/Sub | Channels | PUBLISH, SUBSCRIBE |
| Locking | Strings | SET NX EX, DEL, Lua scripts |
Redis is commonly used for distributed locks via the SET NX EX pattern or the Redlock algorithm for higher reliability. However, for critical distributed coordination, consider purpose-built systems like etcd or ZooKeeper. Redis locks are best for 'best-effort' coordination where occasional double-locking is acceptable.
Redis has spawned a rich ecosystem of modules, clients, and managed services.
Redis Stack (Redis with Modules)
Redis Stack bundles popular modules:
These modules extend Redis beyond key-value into a multi-model database.
Managed Redis Services
| Module | Capability | Example Use Case |
|---|---|---|
| RediSearch | Full-text search, auto-complete | Product search, document retrieval |
| RedisJSON | JSON query and manipulation | User profiles, config storage |
| RedisGraph | Property graph with Cypher | Social networks, recommendations |
| RedisTimeSeries | Time-series aggregation | IoT metrics, monitoring data |
| RedisBloom | Bloom/Cuckoo/Count-Min | Membership testing, frequency estimation |
Redis Forks and Alternatives
The Redis ecosystem includes several notable forks and alternatives:
Client Libraries
Redis clients exist for every major language:
Quality clients handle connection pooling, pipelining, cluster routing, and Sentinel discovery.
In 2024, Redis Ltd. changed the license to SSPL (similar to MongoDB's license change). This led to community forks like Valkey under the Linux Foundation. The practical impact for end-users is minimal, but for companies building managed Redis services, the license distinction matters. Evaluate your needs when choosing between Redis and its forks.
We've covered Redis comprehensively. Let's consolidate the key insights:
What's Next:
We've examined two ends of the in-memory database spectrum: SAP HANA for enterprise OLTP/OLAP, and Redis for high-speed data structure access. Our final page examines persistence options in depth—the mechanisms that allow in-memory databases to survive restarts while maintaining their performance advantages.
You now have comprehensive understanding of Redis: its design philosophy, data structures, performance characteristics, persistence options, clustering approaches, and common use cases. Next, we'll explore persistence options that reconcile in-memory speed with data durability requirements.