Redis vs Memcached Comparison
Amazon ElastiCache supports two open-source engines: Redis and Memcached. Choosing the right engine depends on your use case, data structures, and persistence requirements.
Redis is a versatile in-memory data store supporting complex data structures: strings, lists, sets, sorted sets, hashes, HyperLogLogs, bitmaps, and streams. Redis persists data to disk, supports replication, and offers built-in high availability through failover. It excels at session storage, leaderboards, real-time analytics, and pub/sub messaging.
Memcached is a simpler, multithreaded key-value store optimized for raw speed. It stores only strings, does not persist data, and uses a multi-threaded architecture that takes advantage of multiple CPU cores. Memcached is ideal for simple caching scenarios where you need maximum throughput and low latency.
For example, a gaming leaderboard using sorted sets requires Redis. A simple product catalog cache storing JSON strings as values benefits from Memcached simplicity and throughput.
Redis supports cluster mode with up to 500 nodes per cluster and automatic sharding across slots. Memcached uses consistent hashing for distribution across nodes. Redis Cluster provides built-in failover; Memcached relies on client-side redundancy or ElastiCache Multi-AZ with automatic failover.
Memory efficiency differs too. Memcached uses less overhead per item, making it slightly more memory-efficient for simple key-value pairs. Redis richer data structures consume more memory but provide significantly more functionality.
Cache-Aside, Write-Through, and Write-Behind
Cache strategies define how your application reads from and writes to both the cache and the underlying database. Each strategy offers different tradeoffs between consistency, latency, and complexity.
Cache-Aside (Lazy Loading) is the most common pattern. The application first checks the cache. On a cache miss, it reads from the database, stores the result in the cache, and returns it to the user. Writes go directly to the database, and the cache entry is invalidated. This pattern is simple to implement and only caches frequently accessed data. The downside is a potential cache miss penalty on first access and stale data between invalidation and TTL expiration.
Write-Through writes data to both the cache and database simultaneously. Every write updates the cache, ensuring the cache is always consistent with the database. This pattern provides predictable read performance but increases write latency because every write must complete in both stores. It is useful when you cannot tolerate cache misses for recently written data, such as user profile updates.
Write-Behind (Write-Back) writes to the cache immediately and asynchronously flushes to the database. This provides the fastest write performance but risks data loss if the cache fails before flushing. Write-behind is suitable for high-throughput scenarios like analytics event ingestion where temporary data loss is acceptable.
In practice, combine strategies. Use cache-aside for read-heavy workloads, write-through for critical user data, and write-behind for analytics pipelines. The key principle is choosing the right strategy for each data access pattern rather than applying one strategy universally.
Eviction Policies and TTL Management
When the cache reaches memory limits, eviction policies determine which items to remove. Choosing the right policy impacts cache hit ratios and application performance.
Redis Eviction Policies:
- noeviction: Returns errors when memory is full. Use when you cannot lose cached data.
- allkeys-lru: Evicts least recently used keys across all keys. Best general-purpose policy.
- volatile-lru: Evicts LRU keys only among keys with an expiry set.
- allkeys-random: Evicts random keys. Useful when access patterns are uniform.
- volatile-ttl: Evicts keys with the shortest remaining TTL.
Memcached uses LRU eviction by default and does not support multiple eviction policies.
TTL (Time to Live) is the maximum duration an item remains in the cache. Set TTL based on data volatility. Product prices might have a 5-minute TTL; user sessions might have a 30-minute TTL; static configuration might have a 24-hour TTL.
A common anti-pattern is setting very long TTLs to maximize cache hits. This increases stale data risk. A better approach is using short TTLs with cache-aside: frequently accessed data is refreshed automatically on each miss, while rarely accessed data expires naturally.
Monitor your cache hit ratio using ElastiCache metrics. A hit ratio below 80% suggests either insufficient cache size, poor key design, or inappropriate TTL values. Increasing memory or adjusting TTLs typically improves the ratio.
Redis Pub/Sub and Lua Scripting
Redis provides advanced features beyond simple key-value caching that enable sophisticated application architectures.
Pub/Sub implements a publish-subscribe messaging system. Clients subscribe to channels and receive messages published to those channels. Redis Pub/Sub is fire-and-forget: messages are not persisted and are lost if no subscriber is connected.
For a real-time chat application, users subscribe to channel chat:room:123. When a user sends a message, the application publishes to that channel. All connected users in the room receive the message instantly. Redis Pub/Sub is suitable for real-time notifications, live dashboards, and chat systems where message loss during disconnection is acceptable.
Lua Scripting executes atomic Lua scripts on the Redis server. Scripts have access to all Redis commands and run atomically: no other command can execute during script execution. This eliminates race conditions in complex operations.
For example, a rate limiter script atomically checks a counter, increments it, and sets an expiry all in one script execution. Without Lua, these would be separate commands with potential race conditions between the check and increment.
A real-world example is a distributed lock: a Lua script atomically checks if a key exists, sets it with a TTL if it does not, and returns success. This atomic operation prevents the TOCTOU (time-of-check-time-of-use) vulnerability.
Redis Streams, introduced in Redis 5.0, provide an append-only log data structure with consumer groups. Streams are ideal for event sourcing and message queues with persistence, unlike Pub/Sub which loses messages when subscribers are offline.
Quiz
1. When should you choose Memcached over Redis?
2. What is a drawback of the cache-aside pattern?
3. Which Redis eviction policy is best for general-purpose caching?
4. What makes Redis Lua scripts useful for distributed locks?
5. What is the main difference between Redis Pub/Sub and Redis Streams?
Flashcards
Question
Cache-Aside Pattern
Click to reveal answer
Answer
Application checks cache first. On miss, reads from DB, populates cache, returns data. Writes invalidate cache. Most common caching pattern.
Question
Write-Through Pattern
Click to reveal answer
Answer
Writes go to both cache and database simultaneously. Ensures cache consistency but increases write latency. Good for critical user data.
Question
Write-Behind Pattern
Click to reveal answer
Answer
Writes go to cache immediately, then asynchronously flush to database. Fastest writes but risks data loss. Good for analytics pipelines.
Question
allkeys-lru
Click to reveal answer
Answer
Redis eviction policy that removes the least recently used keys across all keys when memory is full. Best general-purpose policy.
Question
Redis Pub/Sub
Click to reveal answer
Answer
Fire-and-forget messaging system where clients subscribe to channels. Messages are not persisted and are lost if no subscriber is connected.
Question
Redis Lua Scripting
Click to reveal answer
Answer
Executes atomic Lua scripts on the Redis server. Eliminates race conditions in complex operations like distributed locks and rate limiters.
Revision Notes
Key Takeaways
- 1. Redis supports complex data structures, persistence, and replication; Memcached is simpler, faster, multithreaded
- 2. Cache-aside is most common; write-through ensures consistency; write-behind is fastest but risky
- 3. allkeys-lru is the best general-purpose eviction policy
- 4. TTL should match data volatility; short TTLs with cache-aside refresh frequently accessed data automatically
- 5. Redis Pub/Sub is fire-and-forget; Streams persist messages with consumer groups
- 6. Lua scripting provides atomic operations for distributed locks and rate limiting
Interview Tips
- • Explain cache-aside vs write-through vs write-behind with real tradeoffs
- • Discuss when to choose Redis over Memcached based on data structure needs
- • Describe how to calculate and improve cache hit ratios
- • Explain why Lua scripting is necessary for atomic distributed operations
Cheat Sheet
Redis = complex data structures + persistence + replication. Memcached = simple key-value + multithreaded + fast. Cache-aside = check cache, miss reads DB. Write-through = write both simultaneously. Write-behind = write cache, async flush DB. allkeys-lru = best eviction policy. Pub/Sub = fire-and-forget messaging. Streams = persistent messages with consumer groups. Lua = atomic scripting for distributed locks.