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 StringRedisTemplate for 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