Bibliothek / SDK
ben-manes/caffeine avatar
ben-manes/caffeine

Caffeine 3.2.4 im Detail: Java-Caching mit TinyLFU-Verdrängung

Eine Hochleistungs-Caching-Bibliothek für Java. Cache Caffeine bietet einen In-Memory-Cache mithilfe einer von Google Guava inspirierten API.

17.866 Sterne1.714 ForksJavaApache-2.0
GitHub

Auf einen Blick

Was ist das?
Eine In-Memory-Caching-Bibliothek für Java mit von Guava inspirierter API, adaptiver Verdrängung nach Häufigkeit und Aktualität, asynchronem Nachladen veralteter Einträge sowie JCache- und Guava-Adaptern.
Für wen ist es gedacht?
Caffeine passt zu JVM-Servern, deren Datensätze wiederholt gelesen werden und teuer zu berechnen sind, etwa Spring-Dienste mit DB-abhängigen Graphen. Es ersetzt keinen verteilten Cache über mehrere Instanzen hinweg, denn es verwaltet nur den Heap.
Darf ich es kommerziell nutzen?
Ja. Apache-2.0 ist eine freizügige Lizenz: Sie dürfen darauf aufbauende Software nutzen, verändern und verkaufen, solange Sie die Urheberrechts- und Lizenzhinweise beibehalten.
Wird es noch gepflegt?
Ja. Das Repository hat innerhalb des letzten Tages neue Commits erhalten.
In welcher Sprache ist es geschrieben?
Hauptsächlich Java, laut der Sprachstatistik von GitHub.

Die Antworten beruhen auf den GitHub-Daten des Projekts (zuletzt abgeglichen am 15. September 2026) und auf unserer Analyse. Sie sind keine Rechtsberatung.

TIEFGEHENDE OPEN-SOURCE-ANALYSE

Warum Caffeine anstelle einer ConcurrentHashMap

Jedes JVM-Projekt kennt das Problem: Eine Berechnung ist teuer, ein Datenbankzugriff, ein Parserlauf, ein Graphenaufbau, und dieselben Anfragen treffen immer wieder auf dieselben Schlüssel. Eine einfache ConcurrentHashMap löst das nur zur Hälfte. Sie wächst unbegrenzt, kennt keine Ablaufzeiten und wirft nichts heraus, solange der Speicher nicht explizit geleert wird. Genau diese Lücke schließt Caffeine als In-Memory-Cache, der zusätzlich entscheidet, welche Einträge bei Platzmangel gehen müssen.

Das README beschreibt die Bibliothek als leistungsstark und nahezu optimal in Bezug auf Trefferquoten. Die API ist von Google Guavas Cache inspiriert, und die Autoren stützen sich ausdrücklich auf ihre Erfahrungen mit Guavas Cache sowie mit ConcurrentLinkedHashMap, dem Vorgängerprojekt desselben Autors. Caffeine steht unter der Apache License 2.0, zählt rund 17.800 Sterne auf GitHub und wurde am 3. Mai 2026 in Version 3.2.4 veröffentlicht.

Caffeine.newBuilder(): maximumSize, expireAfterWrite, refreshAfterWrite

Der Einstieg ist ein Builder-Ausdruck, wie das README ihn zeigt: LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(Duration.ofMinutes(5)).refreshAfterWrite(Duration.ofMinutes(1)).build(key -> createExpensiveGraph(key)). Drei Richtlinien und eine Ladefunktion stehen in einem einzigen Ausdruck. maximumSize(10_000) begrenzt den Bestand, expireAfterWrite löscht Einträge fünf Minuten nach dem Schreiben, refreshAfterWrite lädt sie bereits nach einer Minute asynchron nach.

Der Unterschied zwischen den beiden Zeitregeln ist praktisch relevant. expireAfterWrite entfernt einen veralteten Eintrag, der nächste Aufrufer wartet dann auf die volle Neuberechnung. refreshAfterWrite dagegen liefert den veralteten Wert sofort zurück und stößt das Nachladen im Hintergrund an, ausgelöst durch die erste veraltete Anfrage. Das README listet diese asynchrone Auffrischung als eigene optionale Funktion. Eine Änderung dieser Richtlinien zur Laufzeit beschreibt das README nicht, sie werden beim Bau des Caches festgelegt.

TinyLFU: Verdrängung nach Häufigkeit und Aktualität

Die eigentliche Ingenieursleistung von Caffeine liegt in der Verdrängungsrichtlinie. Wird das Maximum überschritten, entscheidet nicht eine simple LRU-Reihenfolge, sondern eine Kombination aus Häufigkeit und Aktualität. Das README verweist dafür auf drei in ACM-Publikationen erschienene Arbeiten: TinyLFU von Gil Einziger, Roy Friedman und Ben Manes, dazu Adaptive Software Cache Management und Lightweight Robust Size Aware Cache Management. Alle drei bewerten die von Caffeine eingesetzte Zulassungs- und Verdrängungspolitik.

Ergänzend verlinkt das README zwei HighScalability-Artikel mit dem Titel Design of a Modern Cache in zwei Teilen samt Foliensatz sowie einen Text über das adaptive Fenster für sich verschiebende Zugriffsmuster. Die Ergebnisse der Papiere werden im README selbst nicht zusammengefasst, und die Benchmarks liegen in einem eigenen Wiki-Abschnitt. Wer die Trefferquote für ein konkretes Zugriffsmuster abschätzen will, findet im Simulator, den das README als Erweiterung aufführt, ein Werkzeug, um Richtlinien vor dem Einsatz gegen eigene Traces zu prüfen.

Datenfluss im LoadingCache: Laden, RemovalListener, Statistiken

Um den Ladefunktionskern herum ordnet das README eine Reihe optionaler Bausteine an. Einträge werden automatisch geladen, auf Wunsch asynchron über einen AsyncCache beziehungsweise AsyncLoadingCache. Ein RemovalListener meldet verdrängte oder anderweitig entfernte Einträge, und Schreibvorgänge können über die Compute-Mechanik an eine externe Ressource weitergereicht werden, etwa um einen zweiten Speicherpfad zu pflegen. Für Diagnosen sammelt recordStats() Zugriffsstatistiken, aus denen Trefferquoten und Verdrängungszahlen abgelesen werden können.

Auch Speicherverwaltung lässt sich konfigurieren. Schlüssel können automatisch in schwache Referenzen, Werte in schwache oder weiche Referenzen gehüllt werden, damit der Garbage Collector bei Speicherdruck eingreifen kann. Die Verderbnisgefahr dieser Referenzmodi ist bekannt: Weiche Referenzen können das Verhalten unter Last schwer nachvollziehbar machen, weil die JVM und nicht mehr der Cache über den Bestand entscheidet. Das README empfiehlt keinen der Modi ausdrücklich, es listet sie nur als kombinierbare Optionen.

Gradle-Koordinaten für caffeine 3.2.4 und die Java-11-Grenze

Bezogen wird die Bibliothek über Maven Central, das README zeigt die Gradle-Zeile implementation("com.github.ben-manes.caffeine:caffeine:3.2.4") sowie die optionalen Module guava und jcache in derselben Version. Eine Versionsregel ist beachtenswert: Ab Java 11 ist die 3.x-Linie vorgesehen, ältere Laufzeiten bleiben auf 2.x angewiesen. Projekte, die noch auf Java 8 laufen, können also nicht ohne Weiteres auf 3.2.4 wechseln.

Die Release-Historie zeigt ein gepflegtes Tempo: 3.2.2 erschien am 13. Juli 2025, 3.2.3 am 28. Oktober 2025, 3.2.4 am 3. Mai 2026. Entwicklungsversionen stehen über Sonatypes Snapshot-Repository bereit, Änderungen dokumentieren die Release Notes. Das README enthält allerdings nur ein Gradle-Beispiel, keine Koordinaten für Maven oder andere Build-Werkzeuge; ob und wie diese unterstützt werden, muss über die Maven-Central-Seite des Artefakts geprüft werden.

JCache, Guava-Adapter und die Community-Integrationen

Drei Erweiterungen führt das README ausdrücklich an: die JSR-107-konforme JCache-Anbindung, Adapter für Guava-Caches und der Simulator. Über den JCache-Weg lässt sich Caffeine hinter die standardisierte Cache-API stellen, was den Wechsel zu einem anderen Anbieter später erleichtert. Der Guava-Adapter hilft Bestandsanwendungen, die bereits gegen Guavas Cache programmiert sind, ohne Umbau der Aufrufstellen die Verdrängungslogik auszutauschen.

Die Liste der Community-Integrationen ist lang: Spring Cache, Play Framework, Micronaut, Quarkus, Apache Camel, Bootique und JHipster im Frameworkbereich, dazu Sprachwrapper wie Scaffeine für Scala und Aedile für Kotlin. In der Infrastruktur nutzen Projekte wie Cassandra, Kafka, HBase, Apache Solr, Infinispan und Neo4j die Bibliothek. Das README präsentiert diese Einträge als von der Community bereitgestellt und erklärt nicht, in welcher Form jedes Projekt Caffeine einsetzt; die Liste ist eine Orientierung, keine Unterstützungszusage.

Grenzen von Caffeine und der Weg über den Guava-Cache

Zwei Grenzen gehören in jede Einführungsentscheidung. Erstens bleibt Caffeine strikt prozesslokal, es synchronisiert keinen Bestand über mehrere Instanzen hinweg. Wer in einem Cluster konsistente Cachezustände oder Invalidierung über Knoten braucht, braucht zusätzlich eine verteilte Komponente. Zweitens sind die Richtlinien zur Bauzeit fixiert; das README beschreibt keinen Weg, maximumSize oder Ablaufzeiten im laufenden Betrieb umzustellen. Für Neukonfiguration bleibt nur ein Austausch der Cache-Instanz.

Als konkrete Alternative kommt der Guava-Cache in Frage, aus dessen Design Caffeine hervorgegangen ist. Guava deckt Laden, Ablauf und Größenbegrenzung ebenfalls ab, arbeitet aber mit einfachen qualifizierenden Verdrängungen und ohne die TinyLFU-Statistik, was bei verschiebenden Zugriffsmustern messbar schlechtere Trefferquoten bringen kann. Der Tausch fällt dank der Guava-Adapter und ähnlicher Methodennamen leicht, der Rückweg ebenfalls. Der pragmatische Weg: Caffeine direkt einsetzen, mit recordStats() messen und nur bei Bedarf über den JCache-Weg abstrahieren.

Redaktionelles Fazit

Caffeine passt zu JVM-Servern, deren Datensätze wiederholt gelesen werden und teuer zu berechnen sind, etwa Spring-Dienste mit DB-abhängigen Graphen. Es ersetzt keinen verteilten Cache über mehrere Instanzen hinweg, denn es verwaltet nur den Heap. Wer maximumSize und expireAfterWrite festlegt, sollte zuerst recordStats() aktivieren, die Trefferquote beobachten und den Simulator aus dem Wiki mit eigenen Zugriffstraces laufen lassen, bevor die Werte in Produktion gehen.

Offizielle Quellen

  1. Official README
  2. Project repository
  3. Release notes
Community-Notizen

Community-Notizen