Spring Boot Redis Cache

By Arvind Rai, November 30, 2023
This page will walk through Spring Boot Redis cache example. RedisCacheManager is the CacheManager backed by Redis. If Redis is available and configured in our Spring Boot application, RedisCacheManager will be auto-configured. Redis connections are obtained from Lettuce or Jedis Java Redis clients. Redis dependencies are resolved by spring-boot-starter-data-redis starter. In Spring Boot 2.0 Lettuce are resolved by default instead of Jedis. To work with Jedis, we need to include jedis dependency in our build file.
Spring @EnableCaching enables Spring cache management capability in our application. It is annotated with @SpringBootApplication annotation.

1. Using Lettuce Configurations

Spring Boot 2.0 starter spring-boot-starter-data-redis resolves Lettuce by default. Spring provides LettuceConnectionFactory to get connections. To get pooled connection factory we need to provide commons-pool2 on the classpath. To work with Lettuce we need following Maven dependencies.
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>		
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
</dependency> 
To configure Lettuce pool we need to use spring.redis.* prefix with Lettuce pool connection properties. Find the Lettuce pool sample configurations.
application.properties
spring.redis.host=localhost 
spring.redis.port=6379
spring.redis.password= 

spring.redis.lettuce.pool.max-active=7 
spring.redis.lettuce.pool.max-idle=7
spring.redis.lettuce.pool.min-idle=2
spring.redis.lettuce.pool.max-wait=-1ms  
spring.redis.lettuce.shutdown-timeout=200ms 
We can override default Redis host, port and password configurations. Use max-wait a negative value if we want to block indefinitely.

2. Using Jedis Configurations

By default Spring Boot 2.0 starter spring-boot-starter-data-redis uses Lettuce. To use Jedis we need to exclude Lettuce dependency and include Jedis. Find the Maven dependencies to use Jedis.
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
  <exclusions>
    <exclusion>
	 <groupId>io.lettuce</groupId>
	 <artifactId>lettuce-core</artifactId>
    </exclusion>
  </exclusions>		    
</dependency>		
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
</dependency> 
jedis dependency will automatically resolve commons-pool2 on the classpath.
To configure Jedis pool we need to use spring.redis.* prefix with Jedis pool connection properties. Find the Jedis pool sample configurations.
application.properties
spring.redis.host=localhost 
spring.redis.port=6379
spring.redis.password= 

spring.redis.jedis.pool.max-active=7 
spring.redis.jedis.pool.max-idle=7
spring.redis.jedis.pool.min-idle=2
spring.redis.jedis.pool.max-wait=-1ms 

3. RedisCacheManager

In Spring Boot, RedisCacheManager is auto-configured. Here we will discuss how to configure Spring Boot Redis cache properties to change its default value for auto-configured RedisCacheManager and then we will create a sample own RedisCacheManager to get full control on configurations.

1. Auto-configured RedisCacheManager
If Redis is available and configured in our Spring Boot application, RedisCacheManager will be auto-configured. We can control Spring cache configurations using spring.cache.* property.
spring.cache.type: Defines cache type. If we do not configure this property, It will be auto-detected to the environment. For Redis cache its value is redis .
spring.cache.cache-names: Creates additional caches on startup.

Redis cache defaults can be configured by spring.cache.redis.* .
spring.cache.redis.cache-null-values: It accepts Boolean value. When the value is true, it will allow caching null values otherwise not.
spring.cache.redis.time-to-live: Cache expiration time.
spring.cache.redis.use-key-prefix: It accepts Boolean value. If true then key prefix will be used while writing to Redis. Default value is true
spring.cache.redis.key-prefix: Defines key prefix. By default a key prefix is added to avoid overlapping keys when two separate caches uses same key.

Find the sample Redis cache configurations.
application.properties
spring.cache.redis.cache-null-values=false
spring.cache.redis.time-to-live=600000
spring.cache.redis.use-key-prefix=true

spring.cache.type=redis
spring.cache.cache-names=articleCache,allArticlesCache 
The caches articleCache and allArticlesCache will be alive for 10 minutes.

2. Create own RedisCacheManager
We can create our own RedisCacheManager to get the full control of the Redis configurations. We need to create LettuceConnectionFactory bean, RedisCacheConfiguration bean and RedisCacheManager as following.
RedisConfig.java
@Configuration
@EnableCaching
@PropertySource("classpath:application.properties")
public class RedisConfig {
   @Autowired
   private Environment env;	
	
   @Bean
   public LettuceConnectionFactory redisConnectionFactory() {
	RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
	redisConf.setHostName(env.getProperty("spring.redis.host"));
	redisConf.setPort(Integer.parseInt(env.getProperty("spring.redis.port")));
	redisConf.setPassword(RedisPassword.of(env.getProperty("spring.redis.password")));	    
        return new LettuceConnectionFactory(redisConf);
   }
   @Bean
   public RedisCacheConfiguration cacheConfiguration() {
	RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
	  .entryTtl(Duration.ofSeconds(600))
	  .disableCachingNullValues();	
	return cacheConfig;
   }
   @Bean
   public RedisCacheManager cacheManager() {
	RedisCacheManager rcm = RedisCacheManager.builder(redisConnectionFactory())
	  .cacheDefaults(cacheConfiguration())
	  .transactionAware()
	  .build();
	return rcm;
   }  
} 
RedisCacheConfiguration is immutable class that helps customizing Redis cache behavior such as cache expiry time, disable caching null values etc. It is also helpful in customizing serialization strategy.

4. Enable Caching

To enable cache abstraction in our application, Spring provides @EnableCaching annotation. @EnableCaching enables annotation-driven cache management capability. It is responsible to register required Spring components to enable annotation-driven cache management. @EnableCaching is annotated with @Configuration or @SpringBootApplication annotations.
SpringBootAppStarter.java
@SpringBootApplication
@EnableCaching
public class SpringBootAppStarter {  
    public static void main(String[] args) {
	SpringApplication.run(SpringBootAppStarter.class, args);
    }       
} 

5. Using @Cacheable

@Cacheable indicates that the result of invoking method can be cached and once result is cached, next call to method execution is skipped and only cached result is served. Find the sample code snippet to use @Cacheable annotation.
@Cacheable(value= "articleCache", key= "#articleId")		
public Article getArticleById(long articleId) {
  ------
} 
In the above code, method result will be cached with articleCache cache name using key as passed article id. It means for different article id, result will be cached with different key but with same cache name. Once the method result is cached for a key, then for the same key, method will not execute and the cached result will be served.
Find one more example.
@Cacheable(value= "allArticlesCache", unless= "#result.size() == 0")	
public List<Article> getAllArticles(){
  ------
} 
In the above code, method result will not be cached if size of the result will be 0. If we do not provide key, by default it will be ("") or method parameters are used to compute the key if available.

6. Using @CachePut

@CachePut triggers a cache put operation. It does not skip method execution and result is cached in associated cache for every execution. @CachePut has elements same like @Cacheable such as cacheNames, value, condition, key, unless, keyGenerator etc. Find the sample code snippet to use @CachePut.
@CachePut(value= "articleCache", key= "#article.articleId")
public Article addArticle(Article article){
   ------
} 
The above method will execute for every call and method result will be added or updated in cache corresponding to key for given cache name.

7. Using @CacheEvict

@CacheEvict triggers a cache evict operation. It does not skip method execution and evicts cache for every execution. It has elements such as cacheNames, value, condition, key, keyGenerator, allEntries etc. If allEntries= true, all entries inside the caches are removed. Find the code snippet to use @CacheEvict.
@CacheEvict(value= "allArticlesCache", allEntries= true)	
public void deleteArticle(long articleId) {
  ------
} 
The above method will execute every call and all the entries of caches will be removed.

8. Using @Caching

@Caching is the group annotation for multiple cache annotations. It has cacheable, put and evict elements.
Find the code snippet to use @CachePut and @CacheEvict in group using @Caching.
@Caching(
   put= { @CachePut(value= "articleCache", key= "#article.articleId") },
   evict= { @CacheEvict(value= "allArticlesCache", allEntries= true) }
)
public Article updateArticle(Article article) {
   ------
} 
Find the code snippet to use multiple @CacheEvict in group using @Caching.
	
@Caching(
   evict= { 
	@CacheEvict(value= "articleCache", key= "#articleId"),
	@CacheEvict(value= "allArticlesCache", allEntries= true)
   }
)
public void deleteArticle(long articleId) {
   ------
} 

9. Reference

Spring Boot Reference Guide

10. Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us