Caching in Java: Redis, Caffeine, Ehcache und JCache
Caching ist eines der wichtigsten Werkzeuge zur Leistungssteigerung von Java-Anwendungen. Es ermöglicht, Antwortzeiten zu verkürzen und die Last auf Datenbanken und externe APIs zu reduzieren. In diesem Artikel betrachten wir drei beliebte Lösungen: Redis (externer verteilter Cache), Caffeine (hochleistungsfähiger In-Memory-Cache) und Ehcache (hybrider Cache mit Festplattenunterstützung). Außerdem behandeln wir den Standard JCache (JSR 107), der die Arbeit mit Caches vereinheitlicht.
Warum ist Caching in Java notwendig?
Hauptanwendungsszenarien:
- Reduzierung von Verzögerungen – Daten aus dem Cache werden in Mikrosekunden zurückgegeben, nicht in Millisekunden (wie bei einer Datenbankabfrage).
- Lastreduzierung – Der Cache schützt die Datenbank vor wiederholten Anfragen.
- Ressourcenschonung – Weniger Aufrufe externer Dienste → geringere Infrastrukturkosten.
1. Redis – Verteilter Cache für Microservices
Redis ist ein In-Memory-Datenspeicher, der häufig als verteilter Cache verwendet wird. Er unterstützt verschiedene Datenstrukturen: Strings, Hashes, Listen, Sets. Für Java gibt es zwei Haupt-Clients: Jedis und Lettuce (empfohlen für Spring Boot).
Beispiel für die Einbindung über 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); // teure Abfrage redisTemplate.opsForValue().set(key, user, 10, TimeUnit.MINUTES); return user; }}Vorteile von Redis: Verteiltheit, Unterstützung von TTL, pub/sub, Persistenz. Nachteile: Netzwerklatenz, Speicherverbrauch auf dem Server.
2. Caffeine – Extrem schneller In-Memory-Cache
Caffeine ist eine Bibliothek für lokales Caching, die auf dem W-TinyLFU-Algorithmus basiert. Sie bietet eine nahezu 100%ige Trefferquote bei minimalem Speicherverbrauch. Ideal für Single-Thread- und Multi-Thread-Anwendungen.
Beispiel für die Verwendung von 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));}
// Statistiken abrufenCacheStats stats = cache.stats();System.out.println("Hit rate: " + stats.hitRate());Vorteile von Caffeine: Minimale Latenz (Nanosekunden), integrierte Statistiken, automatisches Verdrängen alter Einträge. Nachteile: Nur lokaler Cache, nicht für verteilte Systeme geeignet.
3. Ehcache – Hybrider Cache mit Festplattenschreibfunktion
Ehcache ist eine der ältesten Caching-Bibliotheken für Java. Sie unterstützt Caching im Arbeitsspeicher und auf der Festplatte sowie Clustering über Terracotta. Wird häufig in Verbindung mit Hibernate verwendet.
Beispiel für die Konfiguration von Ehcache 3 (XML):
<config xmlns:xsi="http://www.w3.org Auch in der Bibliothek
ORM für Rust: Vergleich von Diesel, SeaORM, SQLx und Codebeispiele
Arbeiten mit Bildern in PHP: Überblick über Bibliotheken und Werkzeuge
Datenvalidierung in PHP: Vollständiger Leitfaden zu Tools und Bibliotheken
Arbeiten mit Daten in JavaScript (Node.js): beliebte Bibliotheken