
Spring Data Redis : configuration et cas d'usage (cache, sessions)
Apprenez à configurer Spring Data Redis dans Spring Boot et à l'utiliser pour des cas d'usage clés comme la mise en cache d'applications et la gestion des sessions HTTP distribuées.
Redis : Le couteau suisse de la performance en mémoire
Redis (Remote Dictionary Server) est une base de données en mémoire open-source extrêmement populaire, souvent classée comme un magasin clé-valeur, mais supportant en réalité diverses structures de données (chaînes, listes, sets, sorted sets, hashes, bitmaps, etc.). Sa rapidité fulgurante, due à son fonctionnement principal en mémoire, en fait un outil de choix pour de nombreux cas d'usage visant à améliorer les performances et la scalabilité des applications web.
Spring Boot, via le module Spring Data Redis, offre une intégration simplifiée avec Redis, permettant aux développeurs de l'exploiter facilement pour des tâches courantes comme la mise en cache, la gestion des sessions, la messagerie simple (Pub/Sub), ou comme une base de données clé-valeur rapide.
Ce chapitre se concentre sur la configuration de Spring Data Redis et explore deux de ses cas d'usage les plus fréquents dans l'écosystème Spring : la mise en cache applicative et la gestion des sessions HTTP distribuées.
Configuration de Spring Data Redis
1. Ajouter la dépendance :
La première étape est d'ajouter le starter spring-boot-starter-data-redis à votre projet. Ce starter inclut Spring Data Redis et une bibliothèque cliente Java pour Redis (par défaut, Lettuce est préféré à Jedis dans les versions récentes de Spring Boot).
org.springframework.boot
spring-boot-starter-data-redis
// build.gradle (Gradle)
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// Optionnel : si vous préférez Jedis à Lettuce
/*
configurations {
compileOnly {
extendsFrom annotationProcessor
}
// Exclure Lettuce
implementation('org.springframework.boot:spring-boot-starter-data-redis') {
exclude group: 'io.lettuce', module: 'lettuce-core'
}
// Inclure Jedis
implementation 'redis.clients:jedis'
}
*/
2. Configurer la connexion :
Ensuite, configurez les informations de connexion à votre serveur Redis dans application.properties ou application.yml. Par défaut, Spring Boot essaiera de se connecter à localhost:6379.
# application.properties
# Hôte du serveur Redis (défaut: localhost)
spring.redis.host=127.0.0.1
# Port du serveur Redis (défaut: 6379)
spring.redis.port=6379
# Mot de passe (si configuré sur le serveur Redis)
# spring.redis.password=votre_mot_de_passe
# Index de la base de données Redis à utiliser (0-15, défaut: 0)
# spring.redis.database=0
# Configuration SSL (si nécessaire)
# spring.redis.ssl.enabled=true
# Configuration du pool de connexions (Lettuce ou Jedis)
# spring.redis.lettuce.pool.max-active=8
# spring.redis.lettuce.pool.max-idle=8
# spring.redis.lettuce.pool.min-idle=0
# spring.redis.jedis.pool.max-active=8
# spring.redis.jedis.pool.max-idle=8
# spring.redis.jedis.pool.min-idle=0
Auto-configuration : Avec ces éléments, Spring Boot auto-configure :
- Une
RedisConnectionFactory(utilisant Lettuce ou Jedis). - Un bean
StringRedisTemplate, une spécialisation deRedisTemplateoptimisée pour stocker des chaînes de caractères (le cas le plus courant avec Redis). Il utiliseStringRedisSerializerpour les clés et les valeurs. - Un bean
RedisTemplateplus générique, qui utilise par défautJdkSerializationRedisSerializerpour sérialiser les objets Java. Attention : La sérialisation Java par défaut est souvent déconseillée car elle n'est pas portable entre langages et peut poser des problèmes de sécurité ou de versioning. Il est fréquent de reconfigurerRedisTemplatepour utiliser des sérialiseurs JSON (comme Jackson).
Cas d'usage 1 : Mise en cache avec Spring Cache et Redis
L'un des usages les plus courants de Redis est la mise en cache. L'objectif est de stocker en mémoire (dans Redis) les résultats d'opérations coûteuses (appels base de données, appels API externes, calculs complexes) pour pouvoir les réutiliser rapidement lors d'appels ultérieurs avec les mêmes paramètres, évitant ainsi de refaire l'opération coûteuse.
Spring Boot simplifie grandement cela grâce à l'abstraction Spring Cache et à son intégration avec Redis.
1. Activer le Caching : Ajoutez l'annotation @EnableCaching à l'une de vos classes de configuration (souvent la classe principale @SpringBootApplication).
@SpringBootApplication
@EnableCaching // Active le support de cache de Spring
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
2. Configurer Redis comme Cache Manager : Si spring-boot-starter-data-redis est présent, Spring Boot configure automatiquement Redis comme le gestionnaire de cache par défaut. Vous pouvez néanmoins personnaliser la configuration du cache (durée de vie par défaut, sérialisation des valeurs) via les propriétés :
# application.properties
# Durée de vie par défaut des entrées de cache (format ISO-8601 Duration)
spring.cache.redis.time-to-live= PT10M # 10 minutes
# Préfixe pour les clés de cache dans Redis
spring.cache.redis.key-prefix=myAppCache::
# Utiliser le préfixe pour les clés
spring.cache.redis.use-key-prefix=true
# Mettre en cache les valeurs nulles ? (défaut: false)
# spring.cache.redis.cache-null-values=true
Attention à la sérialisation : Par défaut, Spring Cache avec Redis utilise la sérialisation Java (JdkSerializationRedisSerializer). Pour une meilleure interopérabilité et gestion, il est fortement recommandé de configurer un sérialiseur JSON (voir section sur `RedisTemplate` et la configuration personnalisée).
3. Utiliser les annotations de cache : Annotez les méthodes de vos services que vous souhaitez mettre en cache avec les annotations de Spring Cache (@Cacheable, @CachePut, @CacheEvict).
@Service
public class ProductService {
// Le résultat de cette méthode sera mis en cache dans Redis.
// Le cache s'appelle "products" et la clé sera l'argument 'id'.
@Cacheable(value = "products", key = "#id")
public Product getProductById(Long id) {
System.out.println("--- Récupération du produit " + id + " depuis la BDD --- ");
// Simule un appel BDD coûteux
// return productRepository.findById(id).orElse(null);
return new Product(id, "Produit " + id, BigDecimal.TEN);
}
// Met à jour le produit dans la BDD ET dans le cache.
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
System.out.println("--- Mise à jour du produit " + product.getId() + " --- ");
// return productRepository.save(product);
return product;
}
// Supprime un produit du cache (pas forcément de la BDD ici).
@CacheEvict(value = "products", key = "#id")
public void evictProductCache(Long id) {
System.out.println("--- Suppression du produit " + id + " du cache --- ");
}
}
Au premier appel de getProductById(1L), la méthode sera exécutée et le résultat stocké dans Redis sous une clé comme myAppCache::products::1. Les appels suivants avec le même ID retourneront directement la valeur depuis Redis sans exécuter la méthode.
Cas d'usage 2 : Gestion des sessions HTTP avec Spring Session
Dans les applications web traditionnelles, la session HTTP est souvent stockée en mémoire sur le serveur d'applications. Cela pose problème dans les environnements distribués (plusieurs instances de l'application derrière un load balancer) car une requête utilisateur peut atterrir sur une instance différente de celle qui détient sa session.
Spring Session résout ce problème en externalisant le stockage des sessions dans un datastore centralisé, comme Redis. Toutes les instances de l'application peuvent ainsi accéder aux données de session de n'importe quel utilisateur.
1. Ajouter la dépendance Spring Session :
org.springframework.session
spring-session-data-redis
// build.gradle (Gradle)
implementation 'org.springframework.session:spring-session-data-redis'
// Assurez-vous que implementation 'org.springframework.boot:spring-boot-starter-data-redis' est aussi présent
2. Configurer le type de store :
Indiquez à Spring Session d'utiliser Redis comme magasin de session dans application.properties.
# application.properties
spring.session.store-type=redis
# Optionnel: configurer le timeout de la session Redis (différent du timeout du cookie)
# spring.session.timeout=30m
# Optionnel: configurer le namespace des clés de session dans Redis
# spring.session.redis.namespace=myApp:session
C'est tout ! Avec ces dépendances et cette configuration, Spring Boot et Spring Session remplacent automatiquement la gestion de HttpSession basée sur le conteneur par une implémentation qui stocke les données de session dans Redis. Votre code applicatif qui utilise HttpSession (directement ou via @SessionAttributes, beans de session) continue de fonctionner de manière transparente, mais les données sont désormais stockées et partagées via Redis.
Cela rend votre application web stateful prête pour la scalabilité horizontale.
Accès direct avec `RedisTemplate` et `StringRedisTemplate`
Au-delà du cache et des sessions, vous pouvez utiliser Redis comme une base clé-valeur performante. Spring Data Redis fournit RedisTemplate et StringRedisTemplate pour interagir directement avec Redis.
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class RedisExampleService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// Injecter ValueOperations pour simplifier l'accès aux opérations sur les chaînes
@Resource(name="stringRedisTemplate") // Nécessaire car il y a 2 RedisTemplate beans
private ValueOperations valueOps;
public void saveOtp(String userId, String otp) {
// Stocke une chaîne avec une expiration (ex: pour un mot de passe à usage unique)
String key = "otp:" + userId;
valueOps.set(key, otp, Duration.ofMinutes(5));
System.out.println("OTP stocké pour " + userId + " dans Redis.");
}
public String getOtp(String userId) {
return valueOps.get("otp:" + userId);
}
public void incrementLoginAttempts(String username) {
String key = "loginAttempts:" + username;
valueOps.increment(key); // Incrémente un compteur
stringRedisTemplate.expire(key, Duration.ofHours(1)); // Fait expirer après 1h
}
}
Configuration de la Sérialisation JSON (Recommandé) : Pour stocker des objets complexes autres que des chaînes, il est préférable de configurer RedisTemplate pour utiliser JSON.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// Utiliser String serializer pour les clés
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// Utiliser Jackson JSON serializer pour les valeurs
GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
template.afterPropertiesSet();
return template;
}
}
Conclusion : Redis, un allié puissant pour Spring Boot
Spring Data Redis simplifie considérablement l'intégration de Redis dans les applications Spring Boot. Que ce soit pour améliorer les performances grâce à la mise en cache avec Spring Cache, pour assurer la scalabilité des sessions web avec Spring Session, ou pour utiliser Redis comme un datastore clé-valeur rapide, Spring Boot fournit les outils et l'auto-configuration nécessaires pour être productif rapidement. N'oubliez pas de configurer correctement la connexion et, surtout, de choisir une stratégie de sérialisation appropriée (JSON recommandé) lorsque vous stockez des objets complexes.