๐ง Introduction
Caching is one of the most effective ways to improve performance in microservices and monolithic applications. Redis is an ultra-fast, in-memory key-value store that integrates beautifully with Spring Boot via Spring Cache Abstraction.
This tutorial walks you through setting up Redis as a cache in a Spring Boot application with detailed code, configuration, and explanations.
โ๏ธ Technologies Used
- Spring Boot 3.x
- Spring Web
- Spring Cache
- Spring Data Redis
- Redis Server (locally or Docker)
- Java 17+
- Maven
๐ Project Structure
redis-cache-demo/
โโโ controller/
โ โโโ ProductController.java
โโโ config/
โ โโโ RedisConfig.java
โโโ service/
โ โโโ ProductService.java
โโโ model/
โ โโโ Product.java
โโโ RedisCacheDemoApplication.java
โโโ resources/
โโโ application.properties
๐ง 1. Add Dependencies (pom.xml)
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Redis Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- For JSON Serialization in Redis -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Lombok (Optional) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
๐ 2. application.properties
# Redis config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.timeout=60000
# Logging for visibility
logging.level.org.springframework.cache=DEBUG
๐ Tip: You can run Redis locally with Docker:
docker run --name redis -p 6379:6379 redis
๐ป 3. Main Class with Caching Enabled
@SpringBootApplication
@EnableCaching // ๐ฅ Enables Spring's cache abstraction
public class RedisCacheDemoApplication {
public static void main(String[] args) {
SpringApplication.run(RedisCacheDemoApplication.class, args);
}
}
๐งฉ 4. Model Class: Product.java
package com.example.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {
private Long id;
private String name;
private Double price;
}
๐ก
Serializable
is required because Redis stores data as binary by default.
๐ ๏ธ 5. Redis Configuration
package com.example.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.serializer.*;
import java.time.Duration;
@Configuration
public class RedisConfig {
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5)) // Set TTL for cache
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext
.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}
}
โ๏ธ 6. Service Layer with Caching
package com.example.service;
import com.example.model.Product;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class ProductService {
private final Map<Long, Product> productDb = new HashMap<>();
public ProductService() {
// Simulated database
productDb.put(1L, new Product(1L, "iPhone 14", 89999.0));
productDb.put(2L, new Product(2L, "MacBook Pro", 229999.0));
}
// CACHE READ
@Cacheable(value = "productCache", key = "#id")
public Product getProductById(Long id) {
simulateSlowService(); // Simulate latency
return productDb.get(id);
}
// CACHE WRITE / UPDATE
@CachePut(value = "productCache", key = "#product.id")
public Product updateProduct(Product product) {
productDb.put(product.getId(), product);
return product;
}
// CACHE DELETE
@CacheEvict(value = "productCache", key = "#id")
public void deleteProduct(Long id) {
productDb.remove(id);
}
private void simulateSlowService() {
try {
Thread.sleep(3000); // Simulates DB latency
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
๐ก 7. REST Controller
package com.example.controller;
import com.example.model.Product;
import com.example.service.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/products")
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
// GET (with cache)
@GetMapping("/{id}")
public ResponseEntity<Product> getProduct(@PathVariable Long id) {
return ResponseEntity.ok(productService.getProductById(id));
}
// PUT (update + refresh cache)
@PutMapping
public ResponseEntity<Product> updateProduct(@RequestBody Product product) {
return ResponseEntity.ok(productService.updateProduct(product));
}
// DELETE (evict cache)
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
return ResponseEntity.noContent().build();
}
}
๐งช Example Request Flow
1. First Request (Cache Miss)
curl http://localhost:8080/products/1
โ
Output (slow): 3s response time
โณ DB hit, then cached
2. Second Request (Cache Hit)
curl http://localhost:8080/products/1
โก Output (fast): <1s
โ
From Redis cache
3. Update Request (Cache Refresh)
curl -X PUT http://localhost:8080/products \
-H "Content-Type: application/json" \
-d '{"id":1,"name":"iPhone 15","price":95000}'
โ Redis cache is updated
4. Delete Request (Evict Cache)
curl -X DELETE http://localhost:8080/products/1
โ
Cache for id=1
is evicted
๐ Redis Insight View (Optional GUI)
- Install RedisInsight
- Connect to Redis
- View keys under
productCache::1
, etc.
๐ง Best Practices
- Use meaningful cache names and keys
- Apply TTL (Time-to-live) to avoid stale data
- Avoid caching nulls or sensitive data
- Use cache eviction/update smartly with business logic
- Monitor with tools like RedisInsight or Spring Boot Actuator
๐ Conclusion
Using Redis as a cache in Spring Boot is a must-have performance booster for modern apps. With Spring's @Cacheable
abstraction, it's easier than ever to implement caching with minimal effort.
By understanding how to configure TTL, handle serialization, and update cache entries, you can build robust and performant backend services.
Top comments (0)