This article details the architectural evolution from a monolithic Redis cache to a resilient distributed caching system. It emphasizes solving the "thundering herd" problem and hot-spotting through the adoption of consistent hashing for sharding and incorporating a local L1 cache within service instances. The design aims to minimize network latency and improve scalability and fault tolerance.
Read original on Dev.to #systemdesignA common pitfall in system design is relying on a single-node caching layer, like a standalone Redis instance, for high-traffic applications. While simple to implement, this approach quickly becomes a bottleneck under traffic spikes or "read-after-write storms." When multiple requests attempt to read the same freshly written data, the cache is hammered, often leading to cache misses and subsequent database overload. This scenario dramatically increases latency and can cause system-wide degradation, highlighting the need for a more robust caching strategy.
The core architectural solution presented involves transforming the caching layer into a distributed system comprising a ring of independent shards (e.g., Redis clusters) coupled with a lightweight, in-process L1 cache within each service instance. This design leverages consistent hashing to distribute keys across the shards, ensuring even load distribution and graceful scaling.
+-------------------+ +-------------------+ +-------------------+
| Service Instance | | Service Instance | | Service Instance |
| (L1 cache) | | (L1 cache) | | (L1 cache) |
+----------+--------+ +----------+--------+ +----------+--------+
| | |
| consistent hash ring | |
v v v
+-------------------+ +-------------------+ +-------------------+
| Shard A (Redis) | | Shard B (Redis) | | Shard C (Redis) |
+-------------------+ +-------------------+ +-------------------+In this topology, each client (service instance) first checks its local L1 cache. If a cache miss occurs, the client uses consistent hashing to determine the correct distributed Redis shard for the key and directly queries that shard. This minimizes latency for hot keys via L1 and efficiently distributes load across the L2 (sharded Redis) cache.