Mise en cache en Java : Redis, Caffeine, Ehcache et JCache
La mise en cache est l'un des outils clés pour améliorer les performances des applications Java. Elle permet de réduire le temps de réponse, de diminuer la charge sur les bases de données et les API externes. Dans cet article, nous analyserons trois solutions populaires : Redis (cache distribué externe), Caffeine (cache en mémoire haute performance) et Ehcache (cache hybride avec support disque). Nous aborderons également la norme JCache (JSR 107), qui unifie le travail avec les caches.
Pourquoi la mise en cache en Java est-elle nécessaire ?
Principaux cas d'utilisation :
- Réduction des latences — les données du cache sont renvoyées en microsecondes, et non en millisecondes (comme lors d'une requête à la base de données).
- Diminution de la charge — le cache protège la base de données des requêtes répétitives.
- Économie de ressources — moins d'appels aux services externes → moins de coûts d'infrastructure.
1. Redis — cache distribué pour les microservices
Redis est un stockage de données en mémoire souvent utilisé comme cache distribué. Il prend en charge diverses structures de données : chaînes, hachages, listes, ensembles. Pour Java, il existe deux clients principaux : Jedis et Lettuce (recommandé pour Spring Boot).
Exemple de connexion via Spring Data Redis :
@Configurationpublic class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; }}
@Servicepublic class UserService { @Autowired private RedisTemplate<String, Object> redisTemplate;
public User getUserById(String id) { String key = "user:" + id; User cached = (User) redisTemplate.opsForValue().get(key); if (cached != null) return cached;
User user = database.findUserById(id); // requête coûteuse redisTemplate.opsForValue().set(key, user, 10, TimeUnit.MINUTES); return user; }}Avantages de Redis : distribution, support TTL, pub/sub, persistance. Inconvénients : latence réseau, consommation mémoire sur le serveur.
2. Caffeine — cache en mémoire ultra-rapide
Caffeine est une bibliothèque de mise en cache locale basée sur l'algorithme W-TinyLFU. Elle offre un taux de succès (hit rate) proche de 100 % avec une consommation mémoire minimale. Idéale pour les applications monothread et multithread.
Exemple d'utilisation de Caffeine :
Cache<String, User> cache = Caffeine.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) .maximumSize(10_000) .recordStats() .build();
public User getUser(String id) { return cache.get(id, key -> database.findUserById(key));}
// Obtention des statistiquesCacheStats stats = cache.stats();System.out.println("Hit rate: " + stats.hitRate());Avantages de Caffeine : latence minimale (nanosecondes), statistiques intégrées, éviction automatique des anciennes entrées. Inconvénients : cache local uniquement, ne convient pas aux systèmes distribués.
3. Ehcache — cache hybride avec écriture sur disque
Ehcache est l'une des plus anciennes bibliothèques de mise en cache pour Java. Elle prend en charge la mise en cache en mémoire et sur disque, ainsi que la clustering via Terracotta. Souvent utilisée en combinaison avec Hibernate.
Exemple de configuration Ehcache 3 (XML) :
<config xmlns:xsi="http://www.w3.org