Spring Boot Redis
Redis is an extremely fast data store that keeps information in memory. Applications use Redis to cache results, store login sessions, count requests, and share data between several servers. Reading from memory takes a fraction of the time that a database query needs, so pages load faster and databases carry a lighter load.
Spring Boot connects to Redis through the Spring Data Redis starter and plugs it into the caching system with a single property.
The Desk Notepad Idea
An accountant keeps thousands of records in a filing room down the hall. Walking there for every question wastes time. A notepad on the desk holds the numbers that people ask for most often. The accountant checks the notepad first and visits the filing room only when the answer is missing. Redis is the notepad, and the database is the filing room.
Request
|
Check Redis (notepad)
|
found --> return at once (cache hit)
missing --> query database (filing room)
|
save result in Redis
|
return result (cache miss)
What Makes Redis Different
- Data lives in memory, which gives replies in under a millisecond.
- Every value sits under a key, like a labeled box.
- Keys can expire automatically after a set time.
- Several data types exist beyond plain text.
| Data Type | Description | Typical Use |
|---|---|---|
| String | Text or number under a key | Cached page, counter |
| Hash | Field and value pairs inside a key | User profile |
| List | Ordered items | Recent activity |
| Set | Unique items | Tags, unique visitors |
| Sorted set | Unique items with scores | Leaderboards |
Starting Redis Locally
docker run -d --name redis -p 6379:6379 redis:7The command starts a Redis server on the default port 6379.
Adding the Starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>Connection Settings
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=${REDIS_PASSWORD:}
spring.data.redis.timeout=2sSpring Boot builds a connection factory and a StringRedisTemplate from these values.
Reading and Writing Values
StringRedisTemplate handles text keys and text values.
@Service
public class VisitCounter {
private final StringRedisTemplate redis;
public VisitCounter(StringRedisTemplate redis) {
this.redis = redis;
}
public void saveGreeting(String user, String text) {
redis.opsForValue().set("shop:greeting:" + user, text, Duration.ofMinutes(10));
}
public String findGreeting(String user) {
return redis.opsForValue().get("shop:greeting:" + user);
}
public long countVisit(String page) {
Long total = redis.opsForValue().increment("shop:visits:" + page);
return total == null ? 0 : total;
}
}The Duration argument sets a time to live. Redis deletes the key after ten minutes. The increment method adds one to a counter in a single safe step, so two servers never lose a count.
Working with Hashes
redis.opsForHash().put("shop:user:5", "name", "Mia");
redis.opsForHash().put("shop:user:5", "city", "Paris");
Object city = redis.opsForHash().get("shop:user:5", "city");Caching with Annotations
The cache abstraction connects Redis to normal Spring cache annotations, so business code stays free of Redis commands.
spring.cache.type=redis
spring.cache.redis.time-to-live=10m
spring.cache.redis.key-prefix=shop::
spring.cache.redis.cache-null-values=false
@SpringBootApplication
@EnableCaching
public class ShopApplication {
public static void main(String[] args) {
SpringApplication.run(ShopApplication.class, args);
}
}
@Service
public class ProductService {
private final ProductRepository repository;
public ProductService(ProductRepository repository) {
this.repository = repository;
}
@Cacheable(value = "products", key = "#id")
public Product findById(Long id) {
return repository.findById(id).orElseThrow(() -> new ProductNotFoundException(id));
}
@CachePut(value = "products", key = "#product.id")
public Product update(Product product) {
return repository.save(product);
}
@CacheEvict(value = "products", key = "#id")
public void delete(Long id) {
repository.deleteById(id);
}
}| Annotation | Action |
|---|---|
| @Cacheable | Returns the cached value, or runs the method and stores the result |
| @CachePut | Runs the method and refreshes the cached value |
| @CacheEvict | Removes the cached value |
Storing Objects as JSON
Spring Redis uses Java serialization by default, which produces unreadable bytes. A JSON serializer stores objects in a human-readable format that other tools can inspect.
@Configuration
public class RedisConfig {
@Bean
public RedisCacheConfiguration cacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}
}Other Common Uses
- Session storage: several servers share one login session through Spring Session.
- Rate limiting: a counter with a one-minute expiry limits requests per user.
- Leaderboards: sorted sets rank players by score.
- One-time codes: short-lived keys hold verification codes.
Inspecting Data
docker exec -it redis redis-cli
keys shop:*
get shop:greeting:mia
ttl shop:greeting:miaAvoid the keys command on busy production servers. Use scan for safe iteration.
Best Practices
- Give every key a time to live so memory never fills with stale data.
- Use clear key names with colons, such as shop:product:5.
- Treat Redis as a cache and keep the database as the source of truth.
- Evict or update cached values whenever the source data changes.
- Protect Redis with a password and keep it off the public internet.
- Monitor memory use and the cache hit ratio.
Redis adds speed where it matters most. A small cache layer lowers response times and shields the database during busy periods.
