Redis with Spring Boot: Cache, Pub/Sub, and Beyond
Redis is often called a cache, but it’s much more. Let’s explore its capabilities and how to use it effectively with Spring Boot.
What is Redis?
Redis is an in-memory data store that supports:
- Key-Value Storage: Simple key-value pairs
- Data Structures: Lists, sets, sorted sets, hashes
- Pub/Sub Messaging: Real-time communication
- Streams: Event-driven data pipelines
- Geospatial Indexing: Location-based queries
Why Redis?
- Speed: In-memory operations are lightning-fast.
- Versatility: Supports multiple use cases (cache, queue, etc.).
- Simplicity: Easy to set up and use.
- Scalability: Cluster mode for horizontal scaling.
Common Use Cases
1. Caching
Before:
Database → Application → User
After:
Database → Redis Cache → Application → User
2. Session Storage
Before:
Session stored in application memory (not scalable).
After:
Session stored in Redis (shared across instances).
3. Pub/Sub Messaging
Publisher → Redis → Subscriber(s)
4. Leaderboards
Sorted sets for ranking players or items.
Setting Up Redis with Spring Boot
Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Configuration
# application.yml
spring:
redis:
host: localhost
port: 6379
password: yourpassword
Basic Usage
Storing and Retrieving Data
@Service
public class RedisService {
private final StringRedisTemplate redisTemplate;
public RedisService(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void save(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
Caching with Annotations
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
// Simulate database call
return userRepository.findById(id).orElseThrow();
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
Pub/Sub Messaging
Publisher
@Service
public class MessagePublisher {
private final RedisTemplate<String, String> redisTemplate;
public MessagePublisher(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void publish(String channel, String message) {
redisTemplate.convertAndSend(channel, message);
}
}
Subscriber
@Component
public class MessageSubscriber {
@EventListener
public void handleMessage(String message) {
System.out.println("Received: " + message);
}
}
@Configuration
public class RedisConfig {
@Bean
public RedisMessageListenerContainer container(
RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("my-channel"));
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter(MessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "handleMessage");
}
}
Advanced Features
1. Expiring Keys
redisTemplate.opsForValue().set("key", "value", Duration.ofMinutes(10));
2. Distributed Locks
public boolean acquireLock(String key, String value, long timeout) {
return redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofMillis(timeout));
}
public void releaseLock(String key, String value) {
String currentValue = redisTemplate.opsForValue().get(key);
if (value.equals(currentValue)) {
redisTemplate.delete(key);
}
}
3. Leaderboards
redisTemplate.opsForZSet().add("leaderboard", "player1", 100);
redisTemplate.opsForZSet().add("leaderboard", "player2", 200);
Set<String> topPlayers = redisTemplate.opsForZSet().reverseRange("leaderboard", 0, 10);
Common Pitfalls
1. Overusing Redis
- Don’t use Redis as your primary database.
- Avoid storing large binary data.
2. Key Management
- Use consistent naming conventions (e.g.,
app:module:key
). - Set TTLs for temporary data.
3. Memory Usage
- Monitor memory with
INFO memory
. - Use eviction policies (
allkeys-lru
,volatile-lru
, etc.).
Monitoring and Management
1. Redis CLI
redis-cli
127.0.0.1:6379> INFO
127.0.0.1:6379> KEYS *
2. Spring Actuator
management:
endpoints:
web:
exposure:
include: redis
3. Redis Insights
- GUI tool for monitoring Redis instances.
Bottom Line
- Use Redis for speed-critical operations (cache, session, pub/sub).
- Avoid overloading Redis with non-essential data.
- Monitor memory and key usage regularly.
- Leverage Spring Boot’s integration for simplicity.
Remember: Redis is a powerful tool, but like any tool, it works best when used for the right job.