On this page
Redis with Lettuce
Lettuce is a non-blocking Redis client built on Netty. It is the default Redis client in Spring Boot 2.x+, supporting synchronous, asynchronous, and reactive APIs from a single connection.
Setup
Spring Boot auto-configures Lettuce:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
data:
redis:
host: localhost
port: 6379
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 2
shutdown-timeout: 100ms
Enable pooling:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
Synchronous API
@Service
public class CacheService {
private final StringRedisTemplate redisTemplate;
public void set(String key, String value, Duration ttl) {
redisTemplate.opsForValue().set(key, value, ttl);
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void hashSet(String key, String field, String value) {
redisTemplate.opsForHash().put(key, field, value);
}
}
Asynchronous API
@Service
public class AsyncCacheService {
private final RedisAsyncCommands<String, String> asyncCommands;
public AsyncCacheService(RedisConnectionFactory factory) {
RedisConnection conn = factory.getConnection();
asyncCommands = (RedisAsyncCommands<String, String>)
conn.getNativeConnection();
}
public CompletableFuture<String> getAsync(String key) {
return asyncCommands.get(key).toCompletableFuture();
}
public CompletableFuture<String> setAsync(String key, String value) {
return asyncCommands.set(key, value).toCompletableFuture();
}
}
Reactive API (WebFlux)
@Configuration
public class ReactiveRedisConfig {
@Bean
public ReactiveRedisTemplate<String, String> reactiveRedisTemplate(
ReactiveRedisConnectionFactory factory) {
StringRedisSerializer serializer = StringRedisSerializer.UTF_8;
RedisSerializationContext<String, String> context =
RedisSerializationContext.<String, String>newSerializationContext(serializer)
.value(serializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
}
@Service
public class ReactiveCacheService {
private final ReactiveRedisTemplate<String, String> redisTemplate;
public Mono<String> get(String key) {
return redisTemplate.opsForValue().get(key);
}
public Mono<Boolean> set(String key, String value, Duration ttl) {
return redisTemplate.opsForValue().set(key, value, ttl);
}
}
Pub/Sub
// Publisher
redisTemplate.convertAndSend("notifications", "New order received");
// Subscriber
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener((message, pattern) -> {
String body = new String(message.getBody());
System.out.println("Received: " + body);
}, new ChannelTopic("notifications"));
return container;
}
}
Redis Sentinel
spring:
data:
redis:
sentinel:
master: mymaster
nodes:
- sentinel1:26379
- sentinel2:26379
- sentinel3:26379
Redis Cluster
spring:
data:
redis:
cluster:
nodes:
- node1:6379
- node2:6379
- node3:6379
max-redirects: 3
Best Practices
- Use
StringRedisTemplatefor string operations; configure JSON serializer for objects - Enable connection pooling (
commons-pool2) for high-throughput applications - Use reactive API with WebFlux for non-blocking I/O
- Configure Sentinel or Cluster for production HA
- Monitor connection pool metrics via Actuator