Spring @Cacheable default TTL

44,526

Solution 1

Spring is pretty clear about TTL/TTI (Expiration) and Eviction policies as explained in the core Spring Framework Reference Guide here. In other words, the "defaults" depend entirely on the underlying data store (a.k.a. caching provider) used with the Spring Boot app via the Spring Cache Abstraction.

While Arpit's solution is a nice workaround and a generic, transferable solution across different caching providers (data stores), it also cannot cover more specific expiration/eviction policies, such as the kind of action to perform when an expiration/eviction, say OVERFLOW_TO_DISK, or LOCAL_DESTROY only (such as in a Highly Available (maybe zoned based), distributed scenario), or INVALIDATE, etc.

Usually, depending on the UC, evicting "all" entries is not an acceptable option and is one of the reasons why Spring delegates this responsibility to caching provider as this capability varies highly between 1 provider to another.

In summary... definitely review the requirements for your UC and pair the appropriate caching provider with the capabilities that match your UC. Spring supports a wide variety of caching providers from Redis to Apache Geode/Pivotal GemFire to Hazelcast, etc, each with different/similar capabilities in this regard.

Solution 2

Spring @Cacheable does not have any configurable option to set TTL for the cache though you can build it using @CacheEvict and @Scheduled, as follows:

@CacheEvict(allEntries = true, cacheNames = { "cache_1", "cache_2" })
@Scheduled(fixedDelay = 30000)
public void cacheEvict() {
}

You can find detailed solution/explanation here - Setting TTL for @Cacheable – Spring.

Solution 3

With spring boot, I was able to achieve success with this:

First, you need to add spring-boot-starter-data-redis artifact to your POM file.

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-redis</artifactId> 
</dependency>

After this, you need to add the required the following configurations in your application.properties files:

#------ Redis Properties -------------
spring.cache.type=redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.cache.redis.time-to-live=600000

The property to set is spring.cache.redis.time-to-live (value is in milliseconds. 10 mins was set in this case). With this, @Cacheable works with the set default TTL.

Solution 4

Actually, there is a better way than using @schedule, by extending the cacheManager which defines the ttl: Here is an example :

@Configuration
public class CacheConfig extends CachingConfigurerSupport {

@Value( "${redis.hostname}" )
private String redisHostName;

@Value( "${redis.port}" )
private int redisPort;

@Value("#{${redis.ttl}}")
private int DEFAULT_TTL;


@Bean
public JedisConnectionFactory redisConnectionFactory() {
    JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
    redisConnectionFactory.setHostName(redisHostName);
    redisConnectionFactory.setPort(redisPort);
    return redisConnectionFactory;
}

@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
    redisTemplate.setConnectionFactory(cf);
    return redisTemplate;
}

@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
    cacheManager.setDefaultExpiration(DEFAULT_TTL);
    return cacheManager;
}
}

pom dependency :

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
Share:
44,526
Anand Sunderraman
Author by

Anand Sunderraman

Technology agnostic, (with the exception of .NET, yet to break ice with it), software enthusiast. Use technology as means to solve a problem.

Updated on September 17, 2020

Comments

  • Anand Sunderraman
    Anand Sunderraman over 3 years

    I generally use the @Cacheable with a cache config in my spring-boot app and set specific TTL (time to live) for each cache.

    I recently inherited a spring boot app that uses @Cacheable without explicitly stating a cache manager and ttl. I will be changing it to be explicit.

    But I am not able to find out what are the defaults when there is nothing explicit.

    I did look at the docs but found nothing there

  • Alan Teals
    Alan Teals almost 6 years
    So if you choose this option (I did it), you need to set cache manager in the cacheable method I mean: @Cacheable("cacheName", key = "#keyName", cacheManager = "redisCacheManager")
  • Sarp Kaya
    Sarp Kaya almost 6 years
    I don't really like this method. It's a scheduled task going and evicting the key; instead of leaving it to the redis cache (which is what expire is intended to do anyway)
  • Jonathan Heinen
    Jonathan Heinen almost 6 years
    Not a good idea. If you cache values from an external service and clear the whole cache every 30 seconds then every 30 seconds you will see a high load on the external service, while you probably wanted to introduce caching to reduce the load.
  • Terry Collins
    Terry Collins over 5 years
    The above is valid, but only for spring boot 2.1.X per the docs: docs.spring.io/spring-boot/docs/current/reference/html/…
  • user666
    user666 over 5 years
    This should be the correct answer if using redis and spring boot
  • Kalpesh Soni
    Kalpesh Soni almost 5 years
    you can use PT10M for 10 min duration
  • Kalpesh Soni
    Kalpesh Soni almost 5 years
    also this config wont work if you start defining your own java RedisCacheManager bean and all
  • L.Butz
    L.Butz about 4 years
    How is 10000ms = 1min?
  • Bart Robeyns
    Bart Robeyns over 3 years
    Provides a very easy way to get the most out of the Generic Spring-provided cache, without selecting a specific one (the OP didn't mention a specific one); doesn't fall into the trap of forcing a specific impl on the OP.