Caching in Java: Redis, Memcached und integrierte Lösungen: Fortgeschrittenes Niveau
Caching ist eines der wichtigsten Werkzeuge zur Steigerung der Leistung und Skalierbarkeit von Java-Anwendungen. Auf fortgeschrittenem Niveau steht der Entwickler vor der Wahl zwischen verteilten Systemen (Redis, Memcached) und leichtgewichtigen integrierten Caches (Caffeine, Guava). In diesem Artikel analysieren wir die architektonischen Unterschiede, Anwendungsszenarien und geben praktische Codebeispiele für jede Lösung.
1. Integrierte Caches: Caffeine und Guava
Integrierte Caches arbeiten innerhalb der JVM und benötigen keine externen Dienste. Sie sind ideal für die Speicherung temporärer Daten, die nicht zwischen Knoten synchronisiert werden müssen.
Caffeine – der moderne Standard
Caffeine ist eine hochperformante Bibliothek für Caching in Java, die Guava Cache abgelöst hat. Sie verwendet den Window TinyLFU-Algorithmus für eine effiziente Verdrängung von Einträgen.
// Maven-Abhängigkeit// <dependency>// <groupId>com.github.ben-manes.caffeine</groupId>// <artifactId>caffeine</artifactId>// <version>3.1.8</version>// </dependency>
import com.github.benmanes.caffeine.cache.Cache;import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineExample { public static void main(String[] args) { Cache<String, User> userCache = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(10_000) .recordStats() .build();
// Schreiben userCache.put("user:123", new User("Alice", "alice@example.com"));
// Lesen User user = userCache.getIfPresent("user:123"); System.out.println("Cached user: " + user);
// Atomares Lesen mit Laden User result = userCache.get("user:456", key -> loadUserFromDB(key)); }
private static User loadUserFromDB(String key) { // Simulation des Ladens aus der DB return new User("Bob", "bob@example.com"); }
static class User { private final String name; private final String email;
User(String name, String email) { this.name = name; this.email = email; }
@Override public String toString() { return "User{name='" + name + "', email='" + email + "'}"; } }}Guava Cache – bewährte Lösung
Guava Cache von Google bleibt eine beliebte Wahl für Projekte, die bereits die Guava-Bibliothek verwenden. Es unterstützt verschiedene Verdrängungsstrategien und Listener.
import com.google.common.cache.CacheBuilder;import com.google.common.cache.CacheLoader;import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeUnit;
public class GuavaCacheExample { public static void main(String[] args) throws ExecutionException { LoadingCache<String, String> cache = CacheBuilder.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES) .maximumSize(5000) .removalListener(notification -> System.out.println("Removed: " + notification.getKey())) .build(new CacheLoader<String, String>() { @Override public String load(String key) { return "Computed: " + key.toUpperCase(); } });
// Schreiben cache.put("key1", "value1");
// Lesen mit automatischem Laden String value = cache.get("key2"); System.out.println(value); // "Computed: KEY2" }}2. Verteiltes Caching mit Redis
Redis ist