Mastering Distributed Caching with Redis and Memcached in Spring Boot

This article explains the fundamentals, characteristics, and use‑cases of distributed caching, compares Memcached and Redis, and provides a step‑by‑step Spring Boot implementation with code samples, testing guidance, and solutions to common cache pitfalls such as hot keys, penetration, and avalanche.

ITPUB
ITPUB
ITPUB
Mastering Distributed Caching with Redis and Memcached in Spring Boot

1. Introduction to Distributed Caching

In modern micro‑service architectures, high‑concurrency systems rely on caching to avoid overwhelming backend databases. Introducing a cache layer between services and the DB improves response speed, scalability, and reduces hardware costs.

2. Distributed Cache Basics

2.1 What Is Distributed Cache?

A distributed cache separates the cache component from application instances, allowing multiple services to share the same cache data. It offers high availability, cluster deployment, and a unified caching service.

2.2 Local Cache vs. Distributed Cache

Local cache resides in the same process as the application, providing ultra‑fast access but no data sharing across instances, leading to memory waste. Distributed cache runs as an independent service, enabling data sharing among many applications, though no single solution fits all scenarios.

2.3 Key Characteristics

High performance – stores data in memory as key/value pairs, eliminating disk I/O bottlenecks.

Dynamic scalability – nodes can be added or removed to handle load changes.

High availability – automatic failure detection and failover to prevent service interruption.

Ease of use – simple API, topology‑independent, often with graphical management consoles.

3. Typical Application Scenarios

Page cache – stores HTML, CSS, images for fast web page delivery.

Object cache – second‑level cache for ORM frameworks to reduce DB load.

Session/state cache – keeps user session data for high‑availability clusters.

Parallel processing – shares intermediate computation results.

Event handling – continuous query support for real‑time event streams.

Extreme transaction processing – provides high‑throughput, low‑latency support for financial, telecom, and railway systems.

4. Why Use Distributed Cache?

Adding a cache layer yields three main benefits: (1) faster read speed, (2) significantly improved system scalability, and (3) lower overall cost because a single cache server can replace multiple database instances.

5. Popular Cache Technologies

5.1 Memcached

Memcached is a high‑performance, distributed in‑memory object cache that stores data in a large hash table. Key features include:

Uses physical memory; each process max 2 GB; can run multiple instances on different ports.

Key‑value storage with O(1) lookup.

Simple text‑based protocol, usable via telnet.

Built on libevent for efficient event handling.

Distributed capability depends on the client; servers do not communicate with each other.

LRU eviction and lazy expiration.

No persistence – data is lost on restart.

5.2 Redis

Redis is an open‑source, in‑memory key‑value store that supports persistence (RDB, AOF) and clustering. It offers rich data types (string, hash, list, set, sorted set) and advanced features such as publish/subscribe, key expiration, and transactions.

Read speed up to 110 000 ops/s, write speed up to 81 000 ops/s.

Supports atomic operations and transactions.

Provides pub/sub, notifications, and other extensions.

5.3 Comparison

Memcached excels at simple caching with minimal overhead, while Redis adds data‑structure richness, persistence, and advanced features, making it suitable for more complex use‑cases.

6. Implementing Distributed Cache with Spring Boot + Redis

6.1 Architecture Overview

When a method is invoked, the system first checks the cache. If the key is present, the cached value is returned; otherwise, the database is queried and the result is stored in Redis for future requests.

Cache flow diagram
Cache flow diagram

6.2 Redis Configuration Class

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * Use RedisCacheManager as the cache manager.
     * Supports Redis Sentinel for high availability.
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).build();
        return redisCacheManager;
    }

    /**
     * Custom key generation rule.
     */
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                StringBuilder sb = new StringBuilder();
                sb.append(o.getClass().getName());
                sb.append(method.getName());
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                System.out.println("Generated Redis Cache Key: " + sb.toString());
                return sb.toString();
            }
        };
    }
}

6.3 Using @Cacheable

Annotate data‑retrieval methods with @Cacheable to automatically store results in Redis.

@Repository
public class UserRepository {
    /**
     * Cache the result of user lookup.
     * unless condition can prevent caching when needed.
     */
    @Cacheable(value = "user")
    public User getUserByName(String username) {
        User user = new User();
        user.setName(username);
        user.setAge(30);
        user.setPassword("123456");
        System.out.println("user info from database");
        return user;
    }
}

6.4 Testing the Cache

@Test
public void testGetUserByName() {
    User user = userRepository.getUserByName("weiz");
    System.out.println("name: " + user.getName() + ",age:" + user.getAge());
    user = userRepository.getUserByName("weiz");
    System.out.println("name: " + user.getName() + ",age:" + user.getAge());
}

The first call fetches from the database and populates Redis; the second call hits the cache, as shown in the test logs.

Test result screenshot
Test result screenshot

7. Common Cache Problems and Solutions

7.1 Cache Warm‑up

Pre‑load frequently accessed data into the cache at system startup or on a schedule to improve query efficiency.

7.2 Hot Key

A sudden surge of requests to a single key can saturate network I/O and crash the Redis node. Solutions include sharding the hot key across multiple servers or adding a second‑level in‑memory cache.

7.3 Cache Breakdown

When many requests hit an expired key simultaneously, the database experiences a spike. Mitigation strategies are locking updates or embedding a short TTL in the value and refreshing asynchronously.

7.4 Cache Penetration

Repeated queries for non‑existent keys bypass the cache and hit the DB. Countermeasures: input validation, Bloom filters, or caching null results with a short TTL.

7.5 Cache Avalanche

Massive simultaneous expiration of many keys forces a flood of DB requests. Prevent by assigning varied TTLs, rate‑limiting, or using secondary caches.

8. Cache‑Database Consistency

8.1 Delete‑then‑Update

Deleting the cache before updating the DB can cause stale data if the DB update fails.

8.2 Update‑then‑Delete

If the cache deletion fails after a DB update, subsequent reads may return outdated data.

8.3 Delayed Double Delete

After updating the DB, pause briefly then delete the cache (and optionally delete again after a short interval). This reduces the window where concurrent reads might fetch stale data.

Choosing the appropriate strategy depends on read/write patterns, latency requirements, and the underlying DB‑Redis replication delay.

9. Conclusion

Distributed caching is essential for high‑performance micro‑service systems. Understanding cache types, their characteristics, common pitfalls, and proper Spring Boot integration enables developers and architects to design resilient, scalable applications with minimal cost.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceredisSpring Bootdistributed cacheCache Design
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.