Learnitweb

Implementing Redis Caching in a Spring Boot Application

In this tutorial, we will enhance the Fibonacci Service built earlier by adding Redis caching. This allows us to store previously calculated Fibonacci numbers and avoid recalculating them, significantly improving performance for repeated requests.


1. Why Use Caching?

In computationally heavy operations like Fibonacci calculations:

  • Repeated requests for the same input result in redundant calculations.
  • Using in-memory caching for each instance is inefficient when multiple application instances exist.
  • Redis provides a centralized cache, accessible by all instances, ensuring consistency and improving response time.

2. Project Setup

We assume the Spring Boot project already includes:

  • spring-boot-starter-data-redis
  • Redis server running locally or remotely

3. Configure Cache Manager

Create a separate package called config to configure the cache manager:

package com.example.fib.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;

@Configuration
public class CacheConfig {

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        return RedisCacheManager.builder(redisConnectionFactory)
                                .cacheDefaults(config)
                                .build();
    }
}

Explanation:

  • RedisCacheManager is used to manage caches in Redis.
  • Without this configuration, Spring Boot will default to using a ConcurrentHashMap, storing cache only locally in each instance.

4. Make Fibonacci Method Cacheable

Update the FibonacciService to store results in Redis:

package com.example.fib.service;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class FibonacciService {

    @Cacheable(value = "fibonacci", key = "#index")
    public long getFibonacci(int index) {
        return calculateFibonacci(index);
    }

    private long calculateFibonacci(int index) {
        if (index < 2) return index;
        return calculateFibonacci(index - 1) + calculateFibonacci(index - 2);
    }
}

Key Points:

  • @Cacheable marks the method as cacheable.
  • value = "fibonacci" specifies the cache bucket name in Redis.
  • key = "#index" ensures only the index parameter is used as the cache key, ignoring other parameters.

5. Enable Caching in Spring Boot

Add @EnableCaching to the main application class:

package com.example.fib;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class FibApplication {
    public static void main(String[] args) {
        SpringApplication.run(FibApplication.class, args);
    }
}

6. Handling Multiple Method Parameters

By default, if a method has multiple parameters, Spring will use all parameters to generate the cache key. This may result in redundant entries in Redis.

Example:

@Cacheable(value = "fibonacci", key = "#index")
public long getFibonacci(int index, String name) { ... }
  • Without specifying key = "#index", the cache would consider name as part of the key.
  • Specifying key = "#index" ensures only the Fibonacci index determines the cached value, ignoring irrelevant parameters.

7. Testing the Cache

  1. Start the application.
  2. Call the endpoint multiple times:
GET /fib/45

Observations:

  • First request: Takes time due to calculation.
  • Subsequent requests: Return immediately from Redis cache.
  • Only the relevant index is used as the key.

8. Inspecting Redis

Use redis-cli or a GUI tool:

127.0.0.1:6379> KEYS *
1) "fibonacci::45"
  • Redis stores a hash or serialized object for each cached Fibonacci index.
  • Accessing the same index returns the cached value instantly.

9. Summary

By integrating Redis caching:

  • We avoid recalculating Fibonacci numbers for repeated requests.
  • Performance improves drastically for computationally heavy or frequently requested operations.
  • Multiple application instances can share a centralized cache, maintaining consistency.