JCON Online, September 2022, Dirk Kröhan, (Software Architect) at QAware.
== Dokument bitte herunterladen, falls unscharf! Please download slides if blurred! ==
"There are only two hard things in computer science: cache invalidation and naming things." …und doch kommt man an Caches manchmal nicht vorbei! Spring (Boot) bietet zur Rettung eine praktische Cache Abstraction an, die wir in unserem Projekt eingesetzt haben. Doch was passiert, wenn man von einem simplen in-memory cache auf einen distributed cache umsteigen will, wie z.B. Redis? Geht das wirklich so einfach? Nach einem Einstieg in die Spring Cache Abstraction, geht es um Themen wie Resilient Cache Manager, Cache Poisoning und was es neben klassischen Hit-/Miss-Rate Metriken noch so braucht. Das alles gepaart mit einer Live-Demo in der wir uns gemeinsam Schritt für Schritt die Themen anschauen. Zum Abschluss zeige ich euch gerne noch wie wir Spring Caching mit einer @CollectionCacheable Annotation erweitert haben, was euch als OpenSource Projekt zur Verfügung steht.
8. Vorsicht bei Änderungen an Klassen
QAware | 8
Cluster
my-service
v2
my-service
v1
Load
Balancer
Cache PUT
Serialized Object v2
Cache GET
Expect Object v1
9. ■ Performance Tweak: Pre-Register zu cachende Klassen
– Kryo speichert dann nur einen int Wert für jede Klasse
■ Achtung: Reihenfolge der Klassen muss immer gleich bleiben -> List statt Set
– Hinzufügen von neuen Klassen nur ans Ende der Liste
■ Bei Missachtung: Wilde Exceptions nach Deployment
– z.B.: Kryo versucht Objekt A zu deserialisieren, obwohl Objekt B angefragt wird
Kryo pre-registered classes
QAware | 9
protected KryoSerDes create() {
Kryo kryo = new Kryo();
KRYO_REGISTERED_CLASSES.forEach(kryo::register);
10. ■ Cache-Prefix das vom Deployment abhängt
– z.B. Environment Variable, die eine Application Property überschreibt
– siehe:
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.exter
nal-config
■ Nachteil: Cold Cache nach einem Deployment
– Canary deployment wärmt den Cache vor
Lösung
QAware | 10
private RedisCacheConfiguration getDefaultCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.computePrefixWith(cacheName -> redisCachingConfigurationProperties.getCachePrefix() + cacheName)
…
}
12. Metriken das Must-Have!
QAware | 12
■ Klassische Cache Metriken: Hit-/Miss-Rate
■ Für uns speziell relevant: Metriken zur Latenz
– Separate Metriken für Cache Hit/Miss/Put/Evict
– Am besten direkt als RED-Metric (Rate, Error, Duration)
■ Dedizierte Metriken für spezielle Usecases
– Wie viele Cache / DB Zugriffe für Usecase X
– Summe der Cache / DB Latenzen für Usecase X
• RequestScope Beans als Datencollector
22. Was haben wir gelernt?
QAware | 22
■ Lokale Caches
– Schnell und einfach eingebaut
– Dateninkonsistenz bei > 1 Instanz
• Reduzieren durch passende TTLs
■ Distributed Caching mit Spring Data Redis
– Umstieg kaum Aufwand: Dependency austauschen + CacheManager konfigurieren
– Aber: Objekt (De-)Serialisierung ist jetzt zu beachten
■ Unzuverlässiges Netzwerk
– Resilient Cache Manager: Circuit Breaker um den Cache packen
■ Cache Poisoning
– Konfigurierbarer Cache-Prefix bei Bedarf setzen
– oder automatisiert im Deployment
■ Metriken
– In der Praxis geht es einfach nicht ohne!
– Keine Metriken = Blindflug