Custom TTL for Spring data Redis Cache

Carvia Tech | October 01, 2020 | 2 min read | 2,445 views


Spring Boot 2.2+ provides options to customize Redis Cache using RedisCacheManagerBuilderCustomizer enabling us to set custom value for TTL (time-to-live/expiry) for each of the configured cache.

At the time of writing this article, Spring Boot 2.3.4.RELEASE does not allow configuring TTL value for each individual cache through application.yml, so we need to use RedisCacheManagerBuilderCustomizer if we want to configure different timeout for each individual cache.

Redis Setup

You can easily setup Redis on Ubuntu machine using the below command

Ubuntu 18.04 LTS & 20.04 LTS
$ sudo apt update
$ sudo apt install redis-server

Check redis service status using the below systemctl command:

$ sudo systemctl status redis-server.service

If you are using Mac, then homebrew can be used to quickly install Redis server.

Mac using homebrew
$ brew install redis

On windows, you can get pre-compiled executable of redis from here redislab or here microsoftarchive redis 3.2

Gradle setup

We will be using Spring Boot 2.3.4.RELEASE for this tutorial with dependencies on Spring Data Redis. You can find about Spring Data Redis project here Spring Boot Features

build.gradle
implementation("org.springframework.boot:spring-boot-starter-data-redis")

Spring Boot Redis configuration

We need to configure Spring data redis cache in application.yml for properties hostname, port number and cache names.

application.yml
spring.redis.host: localhost
spring.redis.port: 6379
spring.cache.cache-names: cache1, cache2
spring.cache.redis.time-to-live: 600000   (1)
1 redis.time-to-live allows setting up TTL for the all caches to same value.

The only caveat with this setting (spring.cache.redis.time-to-live) is that you cannot specify custom TTL value for individual cache.

Customize TTL for individual cache in Redis

We will create a custom configuration to create a Bean of type RedisCacheManagerBuilderCustomizer to allow RedisCacheManager configuration. RedisCacheConfiguration allows a method named entryTtl(Duration) that allows us to set custom value for TTL for a given Cache.

RedisConfig.java
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class RedisConfig {

    @Bean
    RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
        return (builder) -> {
            Map<String, RedisCacheConfiguration> configurationMap = new HashMap<>();
            configurationMap.put("cache1", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(20)));  (1)
            configurationMap.put("cache2", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(2)));     (2)
            builder.withInitialCacheConfigurations(configurationMap);
        };
    }

}
1 cache1 will have expiry of 20 seconds from time of creation.
2 cache2 will have expiry of 2 hours from time of creation (time-to-live).

Kotlin equivalent of the same configuration is this:

RedisConfig.kt
@Configuration
class RedisConfig {

    @Bean
    fun redisCacheManagerBuilderCustomizer() = RedisCacheManagerBuilderCustomizer { builder ->
        val configurationMap = HashMap<String, RedisCacheConfiguration>()
        configurationMap["cache1"] = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(20))
        configurationMap["cache2"] = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(2))
        builder.withInitialCacheConfigurations(configurationMap)
    }
}

Now we are good to use Redis cache within our controllers.

Test controller with Redis cache
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RedisTestController {

    @RequestMapping("/hello/{name}")
    @Cacheable("cache1")
    public String hello(@PathVariable String name) throws InterruptedException {
        Thread.sleep(3000);
        return "Hello " + name;
    }
}

If we call GET /hello/carvia, the very first call should take around 3 seconds, subsequent calls should be instant since method invocation results will be cached for next 20 seconds.

That’s all.


Top articles in this category:
  1. Redis rate limiter in Spring Boot
  2. Custom banner in spring boot
  3. Setting a Random Port in Spring Boot Application at startup
  4. Prevent Lost Updates in Database Transaction using Spring Hibernate
  5. Disable SSL validation in Spring RestTemplate
  6. N+1 problem in Hibernate & Spring Data JPA
  7. Spring Data ElasticSearch with Basic Auth


Find more on this topic:
Spring Framework image
Spring Framework

Spring Framework - MVC, Dependency Injection, Spring Hibernate, Spring Data JPA, Spring Boot and Spring Cloud for Microservices Architecture.

Last updated 1 week ago


Recommended books for interview preparation:

This website uses cookies to ensure you get the best experience on our website. more info