Einleitung: Warum ist Caching in Java notwendig?
\nIn der modernen Hochlastentwicklung ist die Geschwindigkeit des Datenzugriffs ein kritischer Faktor. Jede Anfrage an eine Datenbank oder eine externe API erhöht die Antwortzeit und die Belastung der Infrastruktur. Caching in Java ermöglicht es, häufig angefragte Daten im schnellen Arbeitsspeicher (RAM) zu speichern und so die Antwortzeit von Dutzenden Millisekunden auf Mikrosekunden zu reduzieren.
\nIn diesem Artikel betrachten wir drei Hauptansätze für das Caching: integrierte Lösungen (HashMap, Caffeine, Ehcache), Redis und Memcached. Sie erfahren, wie Sie das passende Werkzeug auswählen, und sehen funktionsfähige Codebeispiele.
\n\n1. Integrierte Lösungen für das Caching in Java
\nFür kleinere Projekte oder Single-Thread-Anwendungen reichen oft die integrierten Collections aus. Für die Produktionsumgebung sind jedoch spezialisierte Bibliotheken besser geeignet.
\n\n1.1. Einfacher Cache mit HashMap
\nDer einfachste Weg ist die Verwendung einer ConcurrentHashMap mit manueller Verwaltung der Lebensdauer. Geeignet für Prototypen, bietet aber keine Verdrängungsmechanismen (Eviction).
import java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\npublic class SimpleCache {\n private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();\n\n public void put(String key, Object value, long ttlMs) {\n cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMs));\n }\n\n public Object get(String key) {\n CacheEntry entry = cache.get(key);\n if (entry == null || System.currentTimeMillis() > entry.expiry) {\n cache.remove(key);\n return null;\n }\n return entry.value;\n }\n\n private record CacheEntry(Object value, long expiry) {}\n}\n\n1.2. Caffeine — Hochleistungs-Cache für Java
\nCaffeine ist eine moderne Bibliothek, die in Spring Cache verwendet wird. Sie unterstützt automatische Verdrängung nach Zeit, Größe und Nutzungshäufigkeit.
\nimport com.github.benmanes.caffeine.cache.Cache;\nimport com.github.benmanes.caffeine.cache.Caffeine;\nimport java.util.concurrent.TimeUnit;\n\npublic class CaffeineExample {\n public static void main(String[] args) {\n Cache<String, String> cache = Caffeine.newBuilder()\n .expireAfterWrite(10, TimeUnit.MINUTES)\n .maximumSize(1000)\n .build();\n\n cache.put("user_1", "Alexej");\n String user = cache.getIfPresent("user_1");\n System.out.println(user); // Alexej\n }\n}\n\n1.3. Ehcache — Unternehmensstandard
\nEhcache ist eine ausgereifte Lösung mit Unterstützung für Clustering und Persistenz auf die Festplatte. Wird häufig in Verbindung mit Hibernate verwendet.
\nimport org.ehcache.Cache;\nimport org.ehcache.CacheManager;\nimport org.ehcache.config.builders.CacheConfigurationBuilder;\nimport org.ehcache.config.builders.CacheManagerBuilder;\nimport org.ehcache.config.builders.ResourcePoolsBuilder;\n\npublic class EhcacheExample {\n public static void main(String[] args) {\n CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()\n .withCache("users",\n CacheConfigurationBuilder.newCacheConfigurationBuilder(\n String.class, String.class,\n ResourcePoolsBuilder.heap(100))\n ).build();\n cacheManager.init();\n\n Cache<String, String> cache = cacheManager.getCache("users", String.class, String.class);\n cache.put("user_2", "Maria");\n System.out.println(cache.get("user_2")); // Maria\n\n cacheManager.close();\n }\n}\n\n2. Redis — Verteiltes Caching für Java
\nRedis ist ein In-Memory-Datenspeicher, der als separater S