Spring Boot Redis Cache
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 starterspring-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>
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
max-wait
a negative value if we want to block indefinitely.
2. Using Jedis Configurations
By default Spring Boot 2.0 starterspring-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
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) { ------ }
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(){ ------ }
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){ ------ }
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) { ------ }
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) { ------ }
@CacheEvict
in group using @Caching
.
@Caching( evict= { @CacheEvict(value= "articleCache", key= "#articleId"), @CacheEvict(value= "allArticlesCache", allEntries= true) } ) public void deleteArticle(long articleId) { ------ }