We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Java Caching with JSR107 and tCache

00:00

Formal Metadata

Title
Java Caching with JSR107 and tCache
Title of Series
Number of Parts
84
Author
License
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Caching data is an essential part in many high-load scenarios. A local 1st-level cache can augment a shared 2nd-level cache like Redis and Memcached to further boost performance. JCache (JSR107) is the Java Standard for Caching, and tCache is a production-proof OpenSource JCache provider. This talk presents advanced features of JCache like EntryProcessors and Listeners, and tCache specific cutting-edge features like data-aware evictions, and built-in load-spreading.
16
Thumbnail
41:34
27
Thumbnail
08:57
36
Thumbnail
48:55
56
58
Thumbnail
1:02:53
67
Thumbnail
45:41
68
69
Thumbnail
37:44
Cache (computing)Sound effectDatabaseInterface (computing)ImplementationScaling (geometry)Standard deviationSource codeSurfaceSoftware repositoryProduct (category theory)ArmWebsiteSearch engine (computing)Local ringRAMOpen sourceXMLComputer animationLecture/ConferenceProgram flowchart
Cache (computing)Apache <Programm>RAMData storage deviceData storage deviceNumberComputer animationLecture/Conference
InformationSun <Marke>Source codeORACLSDomain nameTime zoneComputer animation
LengthLaufzeitCache (computing)Eigenvalues and eigenvectorsClefDefault (computer science)Social classObject (grammar)Version <Informatik>MISSHauptspeicherInformationStatistikerListe <Informatik>EckeElement (mathematics)Sound effectBack-face cullingPhysical quantityCASHENetwork topologyComputer animationLecture/Conference
Cache (computing)Limit (category theory)Software testingData storage devicePhysical quantityLecture/Conference
DatabaseXMLCache (computing)Computer animation
Cache (computing)Configuration spaceMilitary operationRoute of administrationWritingHausdorff spaceSocial classWordLecture/ConferenceComputer animation
Military operationSystems <München>Level (video gaming)Cache (computing)BerechnungCodeSet (mathematics)FunktionalitätClefVariable (mathematics)ProzessorComputer animationLecture/ConferenceXML
Eigenvalues and eigenvectorsCodeCache (computing)CodeMilitary operationListe <Informatik>Lösung <Mathematik>Set (mathematics)Lecture/ConferenceXMLComputer animation
Data structureCache (computing)MetadataLecture/ConferenceComputer animation
Cache (computing)HIT <Programm>DatabaseOpen sourceStatistikerLaufzeitUNIXLimit (category theory)BenchmarkEigenvalues and eigenvectorsSIZDatabaseDigital divideMusical ensemblePoint of saleObject (grammar)Lecture/ConferenceComputer animation
CodeBusiness objectEigenvalues and eigenvectorsCountingZeitraumZugriffMetadataObject (grammar)Lecture/ConferenceComputer animation
DatabaseFilm editingCodeBenchmarkLecture/Conference
Cache (computing)Stack (abstract data type)CodeMoment (mathematics)Similarity (geometry)Buffer overflowWeb serviceBerechnungRelational databaseComputer animation
Stack (abstract data type)Fibonacci numberCASHECodePrint <4->Video game consoleZahlRecursive languageComputer animation
Musical ensembleVersion <Informatik>BenchmarkSoftware testingHeuristicTotal S.A.Value-added networkMobile appAdobe InDesignVelocitySingle-precision floating-point formatField extensionVolumetric flow rateSocial classCASHEElement (mathematics)FunktionalitätCache (computing)Sampling (statistics)Computer animationLecture/ConferenceDiagram
SpeicherbedarfMusical ensembleMetadataCASHELaceOverhead (computing)Social classQuarkMittelungsverfahrenDatabase transactionExpert systemAPICache (computing)Ende <Graphentheorie>Liste <Informatik>Computer animationLecture/Conference
InternetServer (computing)Communications protocolLine (geometry)TwitterComputer animation
Lecture/ConferenceComputer animation
Transcript: German(auto-generated)
Gut, ich denke, wir können auch dann einfach relativ pünktlich anfangen. Ja, erst mal willkommen zur Vortrag im Java-Bereich über Caching. Ich spreche vor allem halt tatsächlich über diesen JSA 107.
Das ist halt ein Java-Specification-Request, der sich mit dem Caching beschäftigt, der schon relativ alt ist. Wie alt, zeige ich noch. Und ich spreche auch über Tcache, das eine Implementation, die JSA 107 implementiert. Gut, gehen wir mal direkt rein. Ich sage mal noch mal kurz was zu mir.
Wer bin ich? Gut, mein Name ist Christian Esken. Ich mache schon längere Zeit Open Source. Früher war es mehr im C++-Bereich, KDE-Projekt, aber heutzutage bin ich eher im Java-Bereich, Java-Umfeld unterwegs, insbesondere im Bereich Concurrency, Caching, Site Reliability, Skalierung. Das sind eher heutzutage meine Themen.
Ich arbeite als Developer beziehungsweise Architekt bei Trivago, das ist auch unsere Suchmaschine. Die Frage ist, warum Caching wir dort? Caching ist bei uns immer ein großes Thema, weil z.B. Preise von Partnern erst beschafft werden müssen.
Wir müssen nicht nur Preise aus den Datenbanken schaffen, was manchmal langsam ist. Geschäftspartner, Business Partner, HTTP-Schnittstellen können noch deutlich langsamer sein als reine Datenbanken. Daher caching wir an der Stelle. Heutzutage, das meiste, was ich im Open Source-Bereich beitrage,
findet man auf GitHub. Hier sind zwei Repositories. Erstens mein eigenes, das Christian Esken-Repository. Das Weite ist das von der Firma, wo auch einige Contributions von mir sind, aber auch von vielen anderen Leuten, die bei uns in der Firma arbeiten.
Der Vortrag ist im Wesentlichen in drei Großteile gegliedert. Ich sage erst mal grundsätzlich etwas zu Jcache. Das heißt, was ist das Ding überhaupt? Ist das überhaupt relevant? Wie sind da diese Design-Entscheidungen gefallen? Warum gibt es solche Entscheidungen,
die man so gar nicht nachvollziehen kann, wie man sie das erste Mal sieht? Nutzt das überhaupt jemand? Gibt es Implementierungen? Im zweiten Teil erzähle ich etwas zu Tcache, das ist eine Implemation dieser Standards. Ich zeige da insbesondere, was ist so schwierig am Caching?
Warum kann man nicht einen Caching nehmen, der ist gut für alles. Ich habe schon eine Sache dort hingeschrieben, Evictions. Evictions war immer ein großes Thema. Das heißt, wenn der Cache voll ist, muss man etwas rauswerfen. Das ist eigentlich eines der großen Themen, wo sich Caches unterscheiden.
Letzter Teil. Ich will auch ein bisschen Source Code zeigen. Ich will ein bisschen Action zeigen. Wenn wir noch Zeit haben, was ich hoffe, werde ich auch mal kurz ein bisschen was laufen lassen und ein paar kreative Anwendungsmöglichkeiten für Caches zeigen. Bevor ich jetzt mal auf Jcache selber eingebe, will ich noch mal einfach zeigen, wie die Cache-Welt heutzutage aussieht.
Das ist jetzt eine Beispielklassifikation, wie man Caches klassifizieren kann. Man kann auch beliebige andere Dinge aufziehen. Das ist auch beileibe nicht alle Caches, die heutzutage existieren. Aber ich habe mal einfach aufgeteilt in Caches, die im RAM cache und die im Disk cache, auf der einen Achse und auf der anderen Seite, lokale Caches, Remote Caches und Distributed.
Was ist der Unterschied zwischen Remote und Distributed? Ich habe Distributed vor allem mal unter die, habe ich die gepackt, die wirklich Cluster sind. Wirkliche Cache-Cluster. Das ist keine vollständige Liste, da es noch viel mehr Caches gibt. Auch kann man diskutieren, ob man manche Caches überhaupt einsortieren muss.
Zum Beispiel sieht man hier, ich habe auch Caches aufgeführt, die nichts mit Label zu tun haben. Redis, Memcached, LevelDB, MapDB. Weil das einfach bekannte Produkte sind. Redis könnte man auch sagen, das könnte man auch vielleicht ein Distribute, weil Redis gibt es seit kurzer Zeit, halt auch ein Redis Cluster.
Und auch Caches wie zum Beispiel Apache Ignite und Hazelcast sind zwar Distributed, die kann man aber auch lokal nutzen. Das ist bloß, um mal so eine grundsätzliche Fortschritte davon zu geben, wie die Cache-Welt heute aussieht. Die ist sehr vielfältig. Und die Frage ist, warum ist das so? Die Caches sind alle höchst unterschiedlich ausgerichtet. Die einen wollen sehr schnell sein,
die anderen sind quasi komplette Calculation. Auch Frameworks, die mehr machen als nur Caching. Gut. Eine Sache will ich noch kurz zu sagen, zu RAM und Disk. Das scheint so völlig getrennt zu sein. Jetzt ist es aber so, dass tatsächlich
die meisten Caches darauf spezialisiert sind, entweder die Daten im RAM zu halten oder auf Disk. Aber zum Beispiel weiß man ja auch von der Cassandra als Tor, dass der natürlich auch Daten im Speicher hält. Also die Grenze ist dort nicht so ganz eindeutig. Und es ist auch so, dass die Caches,
die hier alle, zumindest die Caches, die hier Java sind, und die die JSR101-Spec implementieren, die können letztendlich irgendwie auch alle auf Disk schweichern, indem sie quasi ein Write-Through oder da sie Write-Through und Read-Through grundsätzlich unterstützen. Das kann und muss jeder Cache, der JSR107-Jay-Cache unterstützt.
Der muss das können. Erstes Thema, Jay-Cache. Ich sag erstmal grundsätzlich was zum Jay-Cache über die Eigenschaften und was der alles kann. Hier ein bisschen was zur Historie.
Jay-Cache und JSR107 sind einfach mal, ja, Jay-Cache ist einfach der Titel von JSR107. Diese Begriffe werden auch gerne mal synonym verwandt. Der eine sagt JSR107, der andere sagt Jay-Cache. Letztendlich gemeint ist immer dasselbe. Jay-Cache hat eine relativ lange Historie, wie man das sieht.
Die ist original 2001 eingetütet worden und ist tatsächlich 2014 endgültig verabschiedet worden, sodass auch endlich in 2015 mal die Early Adapter begonnen haben, das zu implementieren, wie H-Cache. In diesem Jahr, 2016, gibt es immer mehr, die das tatsächlich auch implementieren.
Warum das so lange gedauert hat, ist erstens, weil man hat auch nicht konsequent immer dran gearbeitet. Es gab für Sun bzw. Oracle auch wichtigere Themen als dieses Thema. Andererseits ist die Speck auch nicht gerade leichtgewichtig. Die ist 150 Seiten dick. Da sind zwar auch Source Code-Auszüge
dabei, aber trotzdem das Ding ist nicht ganz so klein. Was da alles drin ist, komme ich später noch zu. Das heißt, J-Cache ist zunächst mal eine Spezifikation. Ich sage mal ganz kurz, komme ich noch später im Detail zu. Was ist T-Cache? T-Cache ist einfach eine Information dieser Spezifikation. Hat angefangen 2009, da war es natürlich noch nicht JSA 107
compliant, weil JSA 107 ist ja erst hier rausgekommen. Das heißt, wir haben im Jahr drauf auch begonnen, darauf umzubauen, dass wir JSA 107 unterstützen. Und sind 2016 jetzt dabei, quasi compliant zu sein. Ich sage quasi, weil es gibt noch ein paar kleine Quirks, sage ich mal, im Bereich von
Evictions. Wir können da sehr viel mit dem T-Cache. Arbeit aber noch leicht anders. So ist halt die ganze Historie. Und man sieht, 2001 bis 2014 ist wirklich eine lange Zeit. Und wenn man sich das einfach vergleicht, Glicksaw, bis hoffentlich 2017, wir wissen ja nicht,
ob es nochmal verschoben wird. Das hat eine kürze Laufzeit als J-Cache, also als JSA. Also das Ding ist lange, lange, lange, haben wir lange drauf gewartet. Jetzt ist es da. Und daher jetzt auch mal dieser Vortrag. Was kann das? Weil es ist relativ unbemerkt dann plötzlich verabschiedet worden. Und es ist in der Entwickler-Community noch nicht breit aufgenommen
worden. Zumindest, dass das existiert. Also grundsätzlich wäre es erstmal J-Cache. Zumindest gibt es diese Spezifikation, diese 150 Seiten, die ich gemachte. Und wer sich mit JSAs auskennt, der weiß, so eine Spezifikation gibt es immer auch eine Referenzimplementation. Und auch ein Technology Kit,
was überprüft, ob eine Implementation auch konform ist. Das heißt, im Wesentlichen sind das Unittests, wie man fast erwarten könnte. Und diese Unittests, die checken quasi jeden Aspekt ab. Lesen, Schreiben, Statistiken, Write-Through, die checken alles mögliche ab, dass es tatsächlich spezifikationskonform erfolgt.
Es sind ungefähr 500 Unittests. Und so ein einzelner Unittest, der besteht zum Teil wieder aus entweder 1 bis 40 Subtests. Das heißt, letztendlich werden da Tausende von Dingen überprüft. Und das heißt, diese Spezifikation ist auch nicht ganz so trivial umzusetzen.
Im Wesentlichen findet man das Ganze auf GitHub. Das Ganze in KSA findet man auf GitHub, sowohl die SPEC, die Referenzimplementation und das Technology Compatibility Kit, das TCK. Die APA und letztendlich auch die API. Die API findet man unter diesem Artefaktnamen, kann man
in jedem, kann man, ob nun Maven, Gradle oder in jedem anderen System unter quasi unter diesem Namen, unter diesen Koordinaten finden. Version 1.0.0, die ist dort herausgekommen. Es gibt auch keine neuere. Es gibt ganz viele Probleme noch in der Spezifikation, viele Fehler, kleine Unklarheiten. Und es wird wahrscheinlich auch irgendwann eine neue Version geben. Aber aktuell ist das die gültige
und die kann man halt einfach einbinden und dann, wenn man das tut, kann man Playcache verwenden. Heißt, API hat aber in Wirklichkeit auch Klassen, hat in Wirklichkeit auch Klassen drin. Enums, Klassen, Minimalimplantation von bestimmten Dingen. Also auch das ist in der API drin, in diesem Paket,
in dem Artefakt. So, was ist, jetzt will ich mal ein bisschen erzählen, was ist tatsächlich alles in Playcache drin? Warum ist das ganze Ding denn so lang? Warum ist das in 150 Seiten lang? Grundsätzlich, erstmal hat man gesagt, wir einigen uns mal drauf, alles ab Java 6, also SI 6+,
ist kompatibel damit. Das heißt, du musst mindestens damit laufen lassen. Das ist heutzutage nicht wirklich ein Problem, weil, na gut, damals, als man es entwickelt hat, da war Java 6 noch in weiter Ferne. Jetzt ist es da und es ist auch 7 da und 8 da und wahrscheinlich mal 9 da. Also das ist jetzt nicht wirklich ein Problem, aber es heißt auch nicht, dass es dort optimal drin läuft.
Es ist so, dass Java IE 6+, damit kompatibel ist, aber eingebaut in IE als Kernkomponente wird es erst mit Java IE 8. So. Was kann man mit Playcache machen? Was deckt das alles ab?
Letztendlich, man kann Cache erzeugen und auch wieder zerstören. Das Ganze, wenn das in Containern läuft, ist das Problem, man will ja vielleicht am Ende, wenn man zum Beispiel so eine Webapp abreißt, nur die eigenen Caches abreißen und nicht die auch von fremden Webapplikationen. Obwohl das über ein gemeinsames
Framework, obwohl das über ein gemeinsamer API und vielleicht geteilte Klassen geht, soll das isoliert sein. Das unterstützen sie, indem sie Cache Manager haben und du sagst, du reißt nur deine eigenen Cache Manager ab und damit werden deine eigenen Cache Manager zerstört und alles anderes bleibt bestehen. Klassische Cache Operation. Ich sag später noch zu, was der noch
alles hat. Die Klassischen sind natürlich alle da. Get, Put, Replace, Delete, alles da. Ich zeige später noch, was der noch spezielleres hat. Drin ist Expiration. Das heißt, Elemente im Cache können verfallen nach einer definierten Zeit. Wenn sie nicht benutzt, nachdem sie eingefügt worden sind, oder nachdem sie benutzt worden sind, dafür gibt es halt entsprechende Klassen.
Man kann auch eigene Expiration Klassen implementieren, die dann ganz spezielle Dinge tun. Das ist sehr schön. Es gibt Statistiks und da muss man wirklich sehr exakt aufpassen, dass man in der Speck bleibt, weil da gibt es einige sehr exotische
Fälle. Möchte ich an dieser Stelle noch nicht drauf eingehen. Ich sage nur ganz kurz mal so ein Stichwort, wenn man sowas hat wie ein Read Through. Das heißt, wenn der Wert eben nicht im Cache ist, lädt der Cache das. Dann ist natürlich die Frage, und wenn er es dann geladen hat, ist das jetzt ein Miss oder nicht? Und da gibt es ganz viele Fälle in der Expiration, wo man ganz
stark aufpassen muss. Aber das ist halt auch ganz gut. Es ist halt spezifiziert und man kann garantieren, man ist halt sicher, egal, welche Implementation ich benutze, es ist so. Dann, wie werden Werte im Cache gespeichert? Sollte man meinen, ja, ist ja irgendwie im Hauptspeicher, dann speichere ich die einfach per Referenz ab. Das ist schnell und schön.
Das kann man auch tun. Das ist aber nicht der Standard in Playcache. Der Standard ist Store by Value. Jeder Wert, Key und Value muss kopiert werden. Wie auch immer man das tut. Wie auch immer man das tut. Das ist nicht spezifiziert. Das ist wiederum nicht spezifiziert, wie man Dinge kopiert. Es ist nun gesagt,
es muss kopiert werden, beim Reinschreiben und beim Rauslesen. Optional in JSA 107 darf man auch implementieren Store by Referenz. Das gibt man dann an. Das implementiert der Cache. Ich kann auch. Ich kann auch Store by Referenz. Caches, die richtig hoch performant sein wollen,
wollen sicherlich nicht die ganze Zeit Objekte kopieren, serialisieren oder was auch immer, werden höchstwahrscheinlich bei Store by Referenz arbeiten. Aber generisch, wenn man sicher sein will, nachdem man einen Wert in Cache geschrieben hat und auf dem Originalobjekt arbeitet, dass da keine Veränderungen im Cache mehr stattfinden. Unerwartet. Zumöglich noch auf dem Key. Und ich finde es nicht wieder.
Deswegen hat man in JSA 107 auch entschieden, Store by Value ist der Default Modus. Wenn man es andere haben will, muss man es umstellen. Ich habe schon gesagt, Readthrough muss jeder Cache implementieren. Der JSA 107 ist komfortabel. Eine extrem spannende Sache ist Cache Listener. Das heißt, man kann sich
notifizieren lassen, wenn sich im Cache etwas tut. Das heißt, wenn ein Wert entfernt wird, wenn er hinzugefügt wird, wenn er verändert wird, wenn er expired. Über all diese Sachen kann man sich informieren lassen. Man kommt auch genau mit, was genau passiert ist. Ob er nur expired ist oder ob er deleted worden ist, ob er verändert worden ist. All diese Informationen
kann man bekommen. Und das ist relativ komfortabel, weil insbesondere, man könnte ja meinen, es läuft ja alles bei mir, ich weiß ja, was ich reinschreibe und was ich lösche. Andererseits expiren ja auch. Kann man ja auch expiren, habe ich ja gesagt. Expiren ist unterstützt. Wenn ein Wert expired, kriegt man nicht unbedingt,
wann der expired. Und manchmal ist es wichtig zu wissen, was da im Cache ist und wann nicht. Und so bekommt man auch Expirations unter anderem mit. Was noch drin ist, ganz spannend, Caching Annotations. Das heißt, man kann entsprechend annotieren, sagen, das ist jetzt eine Put-Operation, das ist eine Get-Operation. Die Frage ist, wer nutzt das? GlavaE8,
haben wir nicht. Gut, wer sonst noch? Spring, Spring 3.1 und Neuer. 3.1 war die erste Implementation, die es genutzt hat. Die haben auch gesagt, ja, das war die erste, das war wirklich schön. Wenn ihr upgraden könnt, bitte upgrade, weil sie dort einige Verbesserungen dort in dem Bereich gemacht haben. Das ist, was
Jcache alles leisten will und auch tut. Was ist nicht drin? Größenangaben. Man kann nicht festlegen bei Jcache, wie groß der Cache-Line soll. Weder in Elementen, noch in Bytes, noch in sonst was. Ist nicht vorhanden.
Jcache selber sagt dazu, ja, uns ist bewusst in der Realität, es sind Ressourcen limitiert und irgendwie geht das nicht. Das überlassen wir aber bitte den Implementationen. Das ist eine etwas komische Herangehensweise, weil man sagt, eigentlich ist das komisch. Das würde ich erwarten, dass wenn der Hauptspeicher alle ist, dass der gefälligst aufhört,
dass der dann eviktet. Ist aber nicht drin. Der Grund, Sie haben auch explizit gesagt, warum Sie das herausgelassen haben. Der Grund ist der, dass Sie sagen, wir kennen die Cache-Topologie ja gar nicht. Wir sind offen für alle Cache-Topologien. Es kann lokal sein, es kann remote sein. Ich habe gesagt, es gibt ja remote, es gibt
distributed Caches. Und was soll ich denn angeben? Eine Anzahl Elemente, eine Größe in Bytes, ein Gewicht. Und da muss ich ja für alle potenziellen Cache-Knoten das angeben können, haben gesagt, statt irgendwie was zu spezifizieren, was vielleicht am Ende doch irgendeinen nicht komplett erfüllt, lassen wir das offen. Wir machen das gar nicht. Und
jeder, der ein Cache implementiert, muss halt selber dafür sorgen, dass das einstellt weiß. Ist ein bisschen unschön, man muss natürlich sagen, jede praktische Cache-Information hat natürlich ein Cache-Limit, ein Size-Limit. Und viele haben Anzahl Elemente, viele haben auch Byte-Größen, die dann wirklich serialisierte Daten speichern,
die wissen auch genau, wie groß die Daten sind. Ist ein bisschen unschön, aber in der Realität muss man den Cache dann halt sich den konkreten Cache angucken und die Größe setzen. Sie nicht zu setzen, ist gewissermaßen, würde ich sagen, schon strafbar. Also das ist schon sehr gefährlich, weil
das ist fast eine Garantie dafür, dass einem der Hiebspeicher ausläuft. Es gibt überhaupt keine Konfigurationsspezifikation, wie man Caches konfiguriert. Es gibt zwar ein Konfigurationsobjekt, wo ein paar wenige Daten drin sind, wo zum Beispiel festgelegt wird, ist es store-by-value
oder store-by-reference und manche andere Sachen auch. Es steht aber nicht daran, wie man das jetzt konfiguriert. Wird auch den Cache-Implementation überlassen, ob das jetzt eine Property ist, eine XML oder ob man es aus der Datenbank liest oder sich ausdenkt frei, das darf jede Cache-Implementation selber entscheiden. Was auch nicht drin ist,
Administration von Caches, die sagen halt, na gut, ich weiß nicht, was ihr da so implementiert. Administrationstools oder sonstige Sachen ist einfach kein Objektiv. Auch Security. Sagen Sie, gut, wenn ihr Security braucht, ich meine, wenn es ein lokaler Cache ist, der nur euch gehört, braucht ihr vielleicht kein Security, aber
auch da sagen Sie, kümmern uns nicht drum, weil es da viel zu viele Optionen gibt. Um überhaupt mal klarzumachen, wie nutzt man doch so einen Play-Cache?
Es ist nicht schwer. Es ist überhaupt nicht schwer. Hier ist ein ganz einfaches Beispiel. Oben, da hat man den Cache-Manager. Man sagt, irgendwie holt sich diesen Cache-Manager und braucht eine Konfiguration, die irgendwie gefüllt worden ist. Hier machen wir einfach mal eine ganz leere Konfiguration ohne Spezialitäten und erzeugen uns hier ein Cache-Cache gleich Cache-Manager gleich Create-Cache
mit einem Namen und der Konfiguration. So, fertig. Ab jetzt können wir Cachen. Wir können zum Beispiel sagen, Cache-Set. Klasse-Set-Operation. Schreibe Doc rein. Ist der Hund drin. Schön. Können das Ding auch wieder rausholen. Ist es drin. Wunderbar. Das ist natürlich die einfachste aller möglichen Anwendungen und ich zeige mal,
bevor ich jetzt alle Operationen mal zeige, die er so hat, zeige ich mal kurz eine spezielle. Wir haben einen Hund drin. Wir wissen aber natürlich Katzen sowieso viel netter. Jetzt will ich den Hund durch die Katze austauschen. Warum zeige ich dieses Beispiel? Gut, erstmal ist eine Katze drin. In dem Vortrag sind Katzen mandatory. Zweitens, ich zeige eine ganz spezielle Operation.
Das ist Replace. Was ist an Replace so speziell? Das ist eigentlich eine Cass-Operation. Das heißt, ich gucke mir vor den Inhalt an, bevor ich eine Veränderung vornehme. Sind spezielle Operationen. Heißt im konkreten Fall, Hund ist drin. Ich sage, er setzt den Hund durch eine Katze. Ne, ja.
Er setze das Element ein, durch eine Katze, bevor ein Hund drin war. Wunderbar funktioniert. Jetzt tausche ich nochmal den Hund durch einen Bär aus. Bär ist aber eigentlich doof. Funktioniert zum Glück nicht. Im Cache ist aktuell ja kein Hund mehr drin. Hier ist es genau das Conditional. Gucken, was im Cache drin ist.
erst den Set, nach dem er geprüft hat. Ich erwähne das deswegen, weil, um zu erklären, wie grundsätzlich in Place A die Operationen zu verstehen sind. Jede Operation ist grundsätzlich als atomar zu verstehen. Das heißt, alles was man tut, ob nun Get, ein Replace, ein Put,
was auch immer man tut. Von außen sieht es immer aus, als würde es atomar einfach geschehen. Es darf nicht irgendwie so ein inkonstanten Zwischenzustand sein, dass jetzt vielleicht doch irgendwie die Katze und der Hund zusammen sind. Auch wenn es auch nur für einen Nanosekund ist. Das darf nicht passieren. Das sagt die Speck auch relativ eindeutig. Und am Ende gut.
Alles ist gut, Katze ist im Cache. Und ich zeige jetzt mal, das war jetzt halt nur um zu zeigen, es gibt diese Kassoperation. Ich zeige jetzt mal aber, was gibt es überhaupt? Was haben wir? Es gibt einfach, ja? Ja, gerne.
Ja. Nein. Genau auch das. Es gibt dort auch, auch das steht irgendwo in der Speck, dass es gesagt wird, wenn es zurückgekommen ist, dann muss es garantiert sein, dass es auch da ist. Und auch in verteilten Systemen,
selbst wenn ich es noch nicht irgendwo durchgeschrieben habe, aber aus dem Interface heraus, vorne, muss er dir garantieren, dass er das zurückliefert. Die klassischen, einfachen Operationen sind natürlich vorhanden. Das kann auch jeder Cache, der heutzutage schon existiert. Die klassischen Caches, die man ja heutzutage so hat, so ist EHCache, ist relativ bekannt.
Der ging schon ganz lange. Und auch alle anderen können natürlich get put remove. Es gibt die Multi-Value Varianten davon. Get all, put all, remove all. Das heißt jetzt nicht alle, sondern halt ein Set oder eine Map. Put all mit einer Map. Get mit einem Set von Keys. Auch das muss jeder implementieren.
Es gibt ganz interessante Compound mit gets. Es gibt get and put, get and remove, get and replace. Ich persönlich hatte dafür noch keinen Anwendungsfall. Aber man hat es wohl in der Speck aufgenommen, weil es gibt wohl welche. Ich weiß nicht, ob hier im Publikum jemand eine Idee hat, wo man das braucht.
Aber vielleicht kommt jemand mal auf den Fall, dass er das braucht. Interessanter sind wirklich diese CAS-Operationen, die wirklich garantieren, dass die Dinge auch nur wahr passieren. Das heißt, put if absent, nur reintun, wenn es noch nicht da war. Ersetzen, ersetzen, wenn und entfernen. Auch entfernen unter bestimmten Bedingungen.
Interessant sind jetzt noch diese Mutatoren. Was sind Mutatoren? Mutatoren, mit denen kann man im Vorbeigehen den Cache ändern. Das ganze arbeitet mit Entry-Prozessoren. Man sagt einfach invoke.
Und dann kann man eigene Funktionalität aufrufen. Und diese Funktionalität kann im Vorbeigehen alles möglich machen. Die kann Berechnungen ausführen. Man invoked es mit einem Cache-Eintrag oder einem Key. Dann wird es processed, eigener Code wird ausgeführt
und in diesem Stück Code kann man ganz viele Dinge machen. Man kann den Wert verändern. Man kann auch den Cache-Eintrag löschen. Man kann auch zwischendurch noch irgendwelche Berechnungen ausführen. Man kann auch gerne noch zehn Sekunden herumrechnen, bis man weiß, was man mit dem Wert überhaupt tun will. Faktisch ist, man kann ein eigenes Stück Code laufen lassen und am Ende ist es auch wieder atomar.
Die Veränderung passiert atomar. Egal, was man innerhalb des eigenen Codes macht. Man kann den Wert zehnmal verändern. Die Veränderung geschieht erst im Cache. Wenn das eigene Stück Code komplett durchgelaufen ist. Das heißt, wenn ich den Wert siebenmal verändere, nur der allerletzte
Veränderung geht in den Cache. Jetzt sollte man natürlich meinen, das sind ja so viele Operationen, das ist ja die Supermenge von allen Operationen, die man sich so denken kann. Das ist es natürlich nicht. Ich habe mir viele Caches
anguckt und jeder hat mindestens eine Operation, die in Jcache nicht vorhanden ist. Das heißt, jeder, der Jcache implementiert, ist ein Superset davon. Ich habe jetzt mal keinen Java-Cache genommen im Vergleich, sondern den Memcache und zu gucken, was kann der. Es gibt viele Operationen, die sind in allen drin. Get, die heißen halt alle ein bisschen anders.
Einmal heißt put if absent, bei Memcache heißt add, remove heißt delete, put heißt set. Aber man sieht, Memcache hat dann auch Operationen increment, decrement, append, prepend, die halt Jcache nicht kann. So gesehen kann man, die Frage dabei ist halt, kann man
Jcache einfach überstülpen, über eine bestehende Lösung? Sagen, ach, das ist ja toll, das ist ja Standard. Ich packe das jetzt einfach drauf. Vielleicht ja, wenn man einfach Sachen macht wie Get und Put, wenn man wirklich sophisticated Sachen macht, ja nein. Das heißt, die Frage ist, sollte man überhaupt darauf gehen? Mittelfristig ist das sicherlich eine gute Idee, um einfach die Wahl zu haben, zwischen
verschiedenen Implementationen, aber man ist jetzt nicht gezwungen auf Teufel komm raus, jetzt irgendwie auf Glaze A da zu migrieren. Für neue Projekte ist das sicherlich eine gute Sache. Auch wenn man bedenkt, dass Glaze I8 das integriert, dass es gute Integration in Spring dazu gibt. Daher, an der Stelle würde man sagen, jo, gute Idee.
Diese Folie würde ich mal kurz weglassen. Das ist ein etwas komplexeres Setup. Ich sage jetzt stattdessen lieber was zu Tcache. Wie gesagt, Tcache ist eine Implementation.
von Jcache. Und die Frage ist natürlich, bevor ich detailliert eingehe, was Tcache tolles kann, will ich mal kurz darauf eingehen, was ist überhaupt so schwer an Caching? Weil Caching, na ja, man kann ja auch eine Hashtrap nehmen, die kann
auch. Man guckt, ist ja doch ein Key-Value-Store, funktioniert doch, ist doch super. Problem ist, ein Key-Value-Store hat keine Möglichkeit halt direkt auf einer Größenbegrenzung. Es hat keine Expiration, es hat keine Expiration. Das heißt, da fehlt einiges. Und gerade Evictions sind auch tatsächlich die größte Challenge. Das heißt, was mache ich, wenn
so ein Cache voll ist? Wer sich ein bisschen mit Evictions auskennt, es gibt so ein paar Klassiker, LFU, LRU, und man denkt, ja, ist doch toll, LRU, least recently used, wenn ich es lange nicht benutzt habe, das Element, werfe ich es raus. Denkt man sich, ist ja einfach zu implementieren. Ich muss mir ja bloß eine Liste zusätzlich noch halten zu meinem Cache, indem ich weichere,
indem ich quasi jedes Element, wenn es benutzt wird, wieder ganz nach vorne tue, damit es als letztes dann halt eviktiert wird. Und leider, wenn ich so eine linked-List habe, sobald ein Element, wie das E2 zugreife, muss ich ziemlich viel an der Liste ändern. E1
zeigt nicht mehr auf E2, sondern auf E3. E2 zeigt nicht mehr auf E3, sondern halt hier hinten auf das. E3 zeigt nicht da sondern auf das. Das heißt, für eine einzelne Get-Operation muss ich plötzlich drei Referenzen ändern. Und wenn ich jetzt viele, viele Gets habe, komme ich da in ziemliche Probleme. Erstens, weil ich muss letztendlich die Liste locken.
Das ist für, um schnell zu sein, nicht gerade gut. Zweitens, um die Listen zu verwalten, ich brauche Speicher, ich brauche CPU. Und letztendlich so ganz trivial das zu implementieren, wenn man es so trivial implementiert, hat man Probleme. Und ich sage das deswegen, weil ich sage mal, wie Tcache diese Geschichte jetzt gelöst hat. Wie machen wir
Eviction? Tcache hält keine extra Datenstruktur. Überhaupt nicht. Stattdessen schweichert er alle Metadaten, schweichert er seinen Wert in einem Holder, wo sowohl die Datenstruktur, wo sowohl der Wert drin ist, als auch die Metadaten.
Das heißt, ich brauche neben quasi der Hashmap keine weitere Datenstruktur, die ich noch irgendwie managen müsste. Das heißt, ich bin so gut wie die Hashmap. Zweiter Trick, der er macht, ich erlaube das Ding ein bisschen zu überfüllen. Nur ein bisschen. Das heißt, nur um ein bisschen Zeit zu haben, damit der Cache wieder gelehrt werden kann, damit die
Eviction laufen kann. Drittens, weil ich so arbeite, nee, drittens, ich gewicke den Batchless, weil Batchless oft immer effizienter sind als so eine Einzeloperation. Batchless sind oft günstiger.
Und weil ich das in Batchless mache, es ist möglich, das Tcache guckt sich jedes einzelne Element an und ist tatsächlich in der Lage, das beste Element zu evigten. Das heißt, wenn man jetzt LFU oder LRU macht, dann bekommt man auch LFU und LRU und nicht ein ungefähr LFU, LRU über, es gibt viele Caches, die halt einfach samplen. Die sagen, ich gucke mir mal 15 Werte an, da wird schon ungefähr das Beste bei sein.
Und das kann gut gehen, das kann aber auch schrecklich schief gehen. Das kann im Zweifel die Hitrate von 90% auf 10% drücken. Alle angucken es gut, kostet natürlich auch Zeit, das hat auch Nachteile. Funktioniert das?
Antwort Ja. Das sind Benchmarks von vor dem Jahr, als wir Tcache Open Source haben, das ist das erste Mal. Und das ist hier Laufzeit in Sekunden. Wir haben 3 Millionen, das ist jetzt ein Test, wo nur Hits drin sind, Cache Hits. Und hier ist ein Vergleich, zum Beispiel mit, das kann man glaube ich sehr schlecht lesen,
Blau ist Infinispan, Rot ist Guava, ist ja sehr beliebt, aber man sieht, der hat eine ziemlich hohe Laufzeit. IHcache, sehr beliebt, aber Laufzeit ziemlich hoch. Das Orange hier ist Tcache und es gibt noch einen, der auch sehr gut ist, der ist Cache2K. Heutzutage gibt es noch einen weiteren,
Caffeine. Und auch der performt relativ gut und man sieht, dass die klassischen Cache, die früher mal so implementiert worden sind und jetzt nicht mehr großartig gewahrt werden, dass die eigentlich ziemlich weit abfallen. Und quasi die neuen Caches tatsächlich sehr deutlich schneller sind. Was haben
wir, was hat Tcache noch, was Glacache nicht hat? Ich sage hier ganz kurz etwas zu. Sehr schön Ich habe gesagt, es gibt natürlich LFU, LRU, aber vielleicht weiß man ja selber, man kennt seine Business-Objekte sehr gut und weiß selber,
was raus kann. Vielleicht weiß man ja, ist eine Session und wenn es zuletzt benutzt worden ist, dass wir aber auch wieder mit Benutzung oder vielleicht sagen wir, Leute, die einen Artikel im Warenkorb haben, die sind wichtiger als die Leute, die keinen im Warenkorb haben. Also sowas kann man sich denken. Und das heißt, man kann tatsächlich eigene Wickel Policies implementieren. Die sind genauso performant wie LFU und LRU.
Die sind genauso schnell. Size Limit hatte ich gesagt, klar, jeder implementiert das. Wir haben bessere Statistiken. Das heißt, die Statistiken in Glacache lagen einfach, wir bauen eine Hitrate zum Beispiel über die gesamte Laufzeit. Die wird irgendwann so auf einen festen Wert laufen. Wir haben
Weighted Average, so ähnlich wie man das kennt, Load Average unter Unix. Top. Weighted Averages. Und wir haben Randomized Expiration Times. Das ist ganz gut, weil wenn man jetzt 10.000 Elemente in Cache steckt und die verfallen alle zur selben Zeit, muss man dieselben 10.000 Elemente höchstwahrscheinlich zur selben Zeit wieder
alle zur selben Zeit holen. Dann sind die Datenbanken über nicht froh darüber. Lieber ein bisschen verteilen und Tcache hat eingebaute Möglichkeiten dafür. So, jetzt habe ich was gesagt. Eviction Policies kann man implementieren. Man denkt, das ist für euch kompliziert. Ich zeige mal, wie LFU implementiert ist. Das ist die
LFU-Information in Tcache. Das ist eine Zeile. Es ist tatsächlich so, wenn man jetzt eine eigene implementieren will, ist das nicht komplizierter. Eviction Policies haben Zugriff auf Key, Value und alle Metadaten. Das heißt, man kann sich angucken, auch die Verfallszeiten oder einen
Use Count. All das kann man sich angucken, um zu entscheiden, was raus kann. Ich zeige mal eine Beispiel-Information. Wie sieht so eine Eviction Policies aus? Jetzt habe ich mal einen Zwei-Zeilen-Code tatsächlich gemacht. Ein Session. Der holt sich hier die Session. Das ist jetzt wirklich ein Business Object.
Unser eigenes Business Object aus dem Code. Das Ganze ist also type safe. Man muss jetzt nicht irgendwie rumcasten. Das Ganze ist absolut type safe. Und wir holen in return einfach mal die Session Age, also das negative Umhalt, die richtigen früher zu evigten. Und das ist alles, was man machen muss. Und das ist ja schön,
weil manchmal hat man tatsächlich, weiß man selber am besten, welche Objekte rauskönnen. Auch die Folie möchte ich jetzt nicht im Detail eingeben. Das zeigt nur alle Möglichkeiten, wie man Werte aus dem Catch wieder rauskriegt. Man kann sie explizit
löschen. Man kann einfach die Verfallszeit laufen lassen. Aber das Interessante hier drin ist im Wesentlichen diese gelben Dinger. Es sind Verfallsintervalle. Das heißt, man kann tatsächlich in T-Catch Verfallsintervalle angeben, sagen, innerhalb dieses Zeitraums soll das irgendwann mal raus.
So. Jetzt möchte ich noch ein bisschen zeigen, dass das alles auch so ein bisschen realen Hintergrund hat. Dass das tatsächlich auch funktioniert. Ich möchte ein bisschen Code zeigen. Ein bisschen Benchmarks zeigen. Um zu zeigen, dass das alles tatsächlich Hand und Fuß hat.
Die Frage war, man kann Expiration Times angeben und wie das jetzt genau funktioniert. Ob man dort Intervalle angibt. Ich kann das so beantworten. Ja, das ist tatsächlich so. Was man angibt, ist wirklich
die Zeit. Und man kann noch dazu angeben, quasi das Intervalle. Typischerweise würde man jetzt irgendwie angeben, eine Stunde und zehn Minuten, dann würde es irgendwie verfallen zwischen einer Stunde und einer Stunde und zehn Minuten. Wenn man jetzt genau zwischen eine Stunde haben will, geht man halt 55 Minuten an und zehn Minuten, dann liegt man genau mit dem Schnitt
auf der Stunde. Genau so. Und das hat tatsächlich real im System bei uns die Datenbank extrem stark entlastet, weil wir auch so Fälle haben, dass tatsächlich mal 10.000 oder 100.000 Werte mal eben aus der Datenbank gelesen werden. Und wenn die, es ist immer unschön, wenn die zur selben Zeit verfallen,
die kommen gerne auch dann exakt wieder. Und so haben wir einen sehr schön ausgeglichenen Zeitraum, sehr schön ausgeglichenen über die Zeit, das die Datenbank da sehr entspannt sich zurücklehnen kann. Ja, hier ist ein Code-Beispiel. Und zwar wollte ich zeigen, ich habe ja eben mal gesagt, es gibt
Re-Through. Re-Through wird mit sogenannten Casual-Loadern ausgeführt. Das heißt, es gibt ein Stück Code, das weiß, was wenn ein Wert nicht im Cache ist, wird dieses Stück Code ausgeführt, um den Cache damit zu füllen. Das heißt, letztendlich man führt, wenn es einen Loader gibt, führt ein Get
aus und der Wert ist nicht im Cache, wird der Loader aufgerufen. Jetzt zeige ich mal, wie so eine Fibonacci-Berechnung aussieht als Cache. Das ist ein Cache- Loader. Da ist ein Load. Dieser Fall ist kein typischer Fall. Also ich sage mal vorweg, normalerweise
benutzt man Cache-Loader in der Form der Wert sind nicht im Cache. Ich gehe auf meine originale Datensource, zum Beispiel eine Relationale Datenbank, einen HTTP-Service oder sonst was, um die Daten zu holen. Dies hier ist eher eine sehr kreative Art und Weise, mit einem Loader umzugehen. Ich zeige das mal. Dieser Cache-Loader. Nehmen wir an, jemand ruft Get von
20 auf. Dann ist es so, wenn der Cache neu ist, dann ist der Wert sicherlich nicht im Cache und der Loader wird aufgerufen. Wir kommen hier rein mit Load von 20. Dann guckt er, ist der Wert kleiner als 2, ist er nicht. Also retört er Cache Get x-1, also 19. So, was macht dieses Cache Get von 19?
Er guckt in den Cache. Er ist nicht da. Der Loader wird aufgerufen. Wir kommen hier hin. Dann haben wir hier 19. Dann kommt er wieder hin. Dann ist 18. Das heißt, es kommt Get, Load, Get, Load, Get, Load. Das zeigt auch schon, dass man sowas nur mit großem Bedacht tun sollte, wenn man genau weiß, was man tut, weil so kann man sich auch wunderbar
Infinite Recursions, Stack Overflow oder Ähnliches bauen. Aber es hat halt Vorteile. Ich zeige das gleich einfach mal, wie es im Code aussieht. Es hat halt einen Vorteil, dass man tatsächlich Code zu schreiben kann, als genauso, man kann ihn rekursiv schreiben. Er ist bloß
unendlich viel performanter. Ich zeige vielleicht jetzt an der Stelle einfach mal die Code, wie das aussieht. Das ist im Prinzip der komplette Code. Ich versuche mal unten noch.
Ach so, Moment. Ach Moment, ja genau. Jetzt muss ich das irgendwie für alle sichtbar machen. Ich hoffe, das
ist jetzt von der Auflösung noch nicht ganz. Ich denke, das wird von der Größe, ich denke, das kann von der Größe hoffentlich jeder lesen. Ja, was machen wir?
Hier ist im Prinzip derselbe Code, den wir eben hatten. Wir haben gesagt, das ist ein Loader. Hier ist die Load Funktion. Ich habe noch ein System Out Print Line, um zu sehen, was da genau im Hintergrund passiert. Hier ist genau derselbe Code. Wenn man diesen Code mal vergleicht mit der Original Fibonacci Funktion, sieht man, die sieht ja fast gleich aus. Das ist der rekursive Aufruf.
Fib von x, wenn kleiner gleich 2, dann 1, ansonsten rekursiver Aufruf. Hier unten ist es natürlich nicht ganz gleich, aber ich habe ja gerade schon erklärt, faktisch ist es auch eine Rekursion. Die Frage ist natürlich, warum mache ich das Ganze? Das ist ganz so komisch, weil wenn das ja doch ähnlich ist, dann gucken wir uns mal die Performance an. Ich zeige jetzt das erste Mal hier unten.
Hier unten habe ich die Print Fib Funktion. Der ruft das auf und printet dann die Ausgabe. Das heißt, ich rechne hier einmal Fib von 8 und Fib von 46. Lassen wir es mal laufen. Ich hoffe, ich kriege gleich hier die Konsole. Da sieht man, Fib von 8 ist da. Wo ist Fib von 46?
Ist noch nicht da. Ist immer noch nicht da. Wird aber irgendwann kommen. Ich weiß, es dauert nicht sehr lang. Ich habe das eben überprüft. Ist da. Wunderschön. Dauert natürlich lange. Ich könnte das jetzt nochmal laufen. Das wird beim zweiten Mal jetzt nicht schneller.
Jetzt baue ich das hier unten mal hier um und sage, ich rufe jetzt mal hier nicht Fib von X auf, sondern ich rufe stattdessen halt mal Cash Get auf. Und dann schauen wir, wie es jetzt mit der Performance aussieht. Fertig.
Das heißt, er ist sofort fertig. Was ist da genau passiert? Das sieht man etwas besser, wenn ich jetzt vielleicht nicht so ganz Großzahlen einfüge, sondern ich nehme mal vielleicht einfach eine 16.
Was ist da passiert? Wir wollten eben Fib von 8 berechnen. Was tat der Code? Der ist in den Cash Get gegangen, hat gesehen,
ist nicht da. Das heißt, die berechnen jetzt Fib von 8 versucht jetzt auf den Cash Get zu gehen mit X minus 2, also mit 6. Ist immer noch nicht da, ist auch nicht da. Minus 2, 4, 2. 2 ist eine bekannte Zahl, da kommt ein bekannter Wert bei raus, 1, und dann geht der ganze Stack wieder zurück. Und da kommt dann eine Zahl raus.
Hier bei der 16 sieht man es auch sehr schön, 16, 14, 12, 10, 9, 11, 13, 15. Das Schöne hierbei ist, man muss gar nicht den Code großzaltig umstellen, der sieht so aus wie vorher, bloß er rennt halt deutlich performanter. Ist eine relativ ungewöhnliche Art, das zu benutzen,
wie gesagt auch ein bisschen gefährlich, aber kann man tun. Dann mache ich mal im Vortrag hier weiter.
Ich möchte jetzt noch ein bisschen was zur Performance sagen. Gebenchmarkt haben wir das auch, ich habe eben einen gezeigt, ich habe gesagt, der ist ein Jahr alt, das heißt, ist das überhaupt noch alles gültig? Müssen wir mal gucken. Ich habe ja, weil in dem ganzen Jahr wurde die komplette
Klasse A 107 Funktionität hinzugefügt, viel an weiter funktioniert. Die Frage ist, vielleicht ist jetzt komplett kaputt. So, wie geht das aus? So, Benchmarks. Die Frage ist, wie machen wir Benchmarks? Jetzt gibt es zwei Möglichkeiten. Vielleicht gibt es ja schon einen exzellen Benchmark. Dann nutzt man den, zeigt die besten Ergebnisse
und das Publikum ist ganz froh und glücklich, weil sie tolle Werte sehen oder ich schreibe einen eigenen, das heißt, ich fälsche meine Ergebnisse selber. Es ist bekannt, Benchmarks sind gut, Benchmarks lügen aber auch immer, sie werden nie exakt den Fall abdecken, der für ein relevant ist, aber sie geben oft einen guten Hinweis.
Das, was wir getan haben, wir haben tatsächlich einen exzellen Benchmark genommen und ich kann jetzt nicht alle Werte davon zeigen, aber nicht alle Grafen davon zeigen. Leider war der Get so unersichtig, dass er hier auf der Folie nicht gut sichtbar ist. Ich zeige Ihnen ein paar.
Wir können da gerne noch irgendwann drüber gucken. Oder man kann das auch selber laufen lassen. Aber grundsätzlich erstmal schon die Warnung. Egal, was man testet, was ich teste, was alle anderen Cash-Leute testen, am besten mit den eigenen Daten testen. Das ist immer am besten. Nur dann weiß man, ob es tatsächlich für einen auch passt.
Ich will nur sagen, was ist wichtig bei einem Cash? Wie schnell ist er? Das erscheint relativ offensichtlich, weil Cash-Leute Dinge überschleunigen. Das heißt, das gilt für Lesen und Schreiben. Ich habe mal gesagt Speed. Was heißt Speed? Das kann Durchsatz und Latenz sein. Und manchmal ist für einen Latenz wichtiger, manchmal Durchsatz.
Wenn beides gut ist, ist auch schön. Sind wir auch glücklich. Hitrate. Man kann natürlich sehr schnell Cash schreiben, indem man immer Null Returns sagt, ist nicht da. Schnell ist, aber hat keine tolle Hitrate. Also muss man auch auf die Hitrate gucken. Man kann natürlich auch immer Trade-off machen. Geschwindigkeit gegen Speicher
und ähnliche Dinge. Und dazu kommen wir zum Speicher. Wie viel Speicher verbraucht das ganze Ding denn? Ich kann es natürlich riesen aufblasen, eine tolle Datensstruktur ausdenken und wenn es dann nicht mehr in den Hauptschlecher passt, hilft mir das auch nicht. Das heißt, das sind ganz wichtige Kriterien für einen Cash, insbesondere wenn es um High-Performance geht. So, das zur
Methodologie. Ich zeige jetzt mal, was dabei rausgekommen ist. Das sind Werte von vorgestern. Der Test, der hier durchgefahren ist, ist von dem Cash 2K-Projekt. Auch der Test vorher war aus dem Cash 2K-Projekt. Die haben aber jetzt gerade umgestellt ihren Normaltest auf GMA-Test.
Das heißt, klar war Micro-Benchmark gegen Harness, was für Cash eine extrem gute Idee ist, weil es tatsächlich ein ganz klassischer Fall für ein Micro-Benchmark ist. Neueste Version, die gerade im Master Herum liegt, die mehr oder weniger stabile Version vom T-Cash. Da steht jetzt 0.95. Ist die stabil?
Warum steht da 0.95? Ja, die ist stabil. Die nutzen wir seit neun Jahren. Und das funktioniert sehr schön. Nicht gerade diese Version, aber der Cash ist ja entsprechend so. Und die läuft so live. Die läuft so live. Die heißt deswegen 0.95, weil noch ein paar AP-Changes sind, noch ein paar Packet-Changes. Die 1.0
hat die Packet-Changes dann und dann ist gut. Der Benchmark. Was tun die dort? Die vergleichen immer auch gegen Concurrent-Hash-Map. Concurrent-Hash-Map, wie schon erwähnt, ist natürlich kein Cash. Warum es drin ist, um mal einen Vergleich zu haben, wie gut man
vielleicht werden kann, weil der eviktiert ja nicht und besser als Concurrent-Hash-Map zu werden schafft. Top. Respekt. Wenn nicht, schauen wir mal, wie gut wir werden. Und jetzt schauen wir mal, wie das in der neuen Version ist. Hier sieht man, inzwischen sind die getesteten Cashless in der neuen Version näher aneinander zusammengekommen.
Es gibt inzwischen neu Kaffein, der war im vorigen Mal nicht drin. Kaffein habe ich gesagt neu, schlägt sich schon relativ gut. IH Cash war vorher drin, ist in einer etwas neueren Version getestet, ist allerdings noch IH Cash 2. Dazu muss man sagen, IH Cash 2
hat keine JSA 107, da gibt es eine Erweiterung, aber IH Cash 2 hat es nicht. IH Cash 3 hat es, war aber dort in dem Benchmark neu implementiert. Man kann es nicht sicher sein, aber typischerweise, wenn man es implementiert, würde man davon ausgehen, dass es vermutlich ein bisschen langsam wird, wegen den erweiterten Funktionalitäten, die man bereitstellen muss. Kann man auch nicht wissen,
bevor man es nicht getestet hat. Guava ist weiter drin. Man sieht, Guava ist nicht ganz so schrecklich, wie in dem Test davor. Warum, wissen wir nicht, ob sie dann gearbeitet haben oder ob dieser Test einfach besser ist. Wie man hier sieht, IH Cash, wir haben jetzt aus dem letzten Jahr eigentlich nur Funktionalitäten hinzugefügt. Da ist noch nichts weiter optimiert worden.
Schlägt sich tatsächlich extrem gut. Hier auf der X-Achse sind die Anzahl der Elemente, die in IH Cash drin sind. Y-Achse, wie lange hat es gelaufen? Das heißt, kleinere Werte sind besser. Ist im 1-Million-Fall der Schnellste, bei 4 Millionen. Auch noch bei 8 Millionen, merkt man,
IH Cash 2 ist wahnsinnig schnell geworden. Ist wahnsinnig schnell geworden bei vielen Elementen. Das ist eine spannende Sache. Warum? Müssen wir mal gucken. Müssen wir mal gucken, wie das ist. Ich weiß, dass die Cash dort Probleme hat, weil ich sagte, ich arbeite batched, ich arbeite auf allen Elementen, bei 8 Millionen ist das schon ziemlich heftig. Da ist eine Sache,
auf der man tatsächlich noch gearbeitet, auf der Arbeit geplant ist. Aber 8 Millionen Elemente sind auch schon ganz schön viele für IH Cash. Die Fälle gibt es, aber auch die sollen natürlich optimiert werden. Das Lesen. Das Schreiben.
Populate. Die Lesen, wie gesagt, ich konnte sie nicht sinnvoll auf die Folien bringen. Das war so klein. Kann man aber auch auf der Cash2K Seite die anderen Benchmarks bisher ohne T-Cash noch nachlesen. Und als drittes habe ich gesagt, Heap ist wichtig.
Und da sieht man, wie schlagen die sich. Hier ist Total Heap. Das Orangen, das würde ich erstmal nicht ernst nehmen, weil das bloß wie viel die Virtual Machine irgendwann mal allokiert hat. Interessanter ist, wie viel hat er überhaupt am Ende verbraucht. Da sieht man, die liegen violett, grün und blau. Man sieht, die liegen alle so ein paar. T-Cash ein bisschen niedriger. Das Spannendste für mich persönlich war,
dass ich sehe, es gibt noch die Allocation Rate, wie viel Megabyte pro Sekunde werden allokiert. Das T-Cash tatsächlich, das hat mich persönlich sehr erstaunt, tatsächlich sehr wenig allokiert. Das ist gut für einen Garbage-Collector klassischerweise, weil sollten diese Daten irgendwann mal tatsächlich in die Old Generation gelangen, könnte das für die Performance ziemlich
unangenehm werden. Das war es jetzt fast. Noch einen ganz kurzen Ausblick. Was passiert in Zukunft? Erstens klar, wir müssen noch die JSA 107 Compliance Certification machen. Das erwarte ich jetzt im nächsten Monat.
Damit wir bei Rides zum Teil schneller werden, ich habe gesagt, wir gucken uns alle Elemente an. Das ist meistens gut, da kommen wir zu guten Ergebnissen, aber manchmal, wenn die Caches sehr groß sind, reicht vielleicht doch ein Sampling. Da wird es noch überlegen,
ob man bei großen Caches das optimiert, indem man ob man doch über Heuristiken oder andere Verfahren schneller bekommt. Es gibt noch ein Szenario, das habe ich nicht gezeigt. Wir haben so Low-Hit-Rate-Szenarien, wo man fast nie trifft, wo es aber trotzdem wichtig ist, die Daten zu liefern.
Da gibt es tatsächlich manche Caches, die sind noch schneller, da wollen wir noch was tun. Was relativ spannend ist Off-Heap. Momentan sind die ganzen Daten im Heap. Aber wenn die Daten nicht allzu oft gelesen werden, macht es manchmal auch Sinn, die Off-Heap zu speichern. Das heißt, auch das ist eine nächste Schritte, nachdem wir die Version 1.0 tatsächlich raus haben. Dann kommt dieses.
So viel dazu. Ich habe noch eine, ich könnte noch einmal etwas vormachen,
aber ich frage erst mal kurz, ob es Fragen gibt. Ja, ich fange mal dort an. Du warst der Erste.
Proprietär auf jeden Fall. Da gibt es einen Cache, gerade im Bereich, der dich am Anfang vorgestellt hat, die verteilten Caches. Da gibt es einige, die auch Transaktionen können. Ich glaube, Infinispan, Hazelcast können das. Wahrscheinlich auch Ignite. Da müsste man im Detail nochmal gucken.
Ich weiß auf jeden Fall, die gibt es. Aber im Playcache selbst ist es zunächst mal nicht vorgesehen. Da war eben die Meldung erst.
Ist das stabil? Ja, das ist stabil. Damit machen wir Geld. Api-stabil.
Api-stabil. Wenn es September, die Frage war, wann ist das stabil? Von der Api kann man dann noch Änderungen erwarten. Und da kann ich einfach sagen, September, es geht jetzt nur noch darum, ein paar Pakete zu verschieben.
Was JSA 107, was die J-Cache betrifft, ist es auch jetzt stabil. Man kann damit komplett arbeiten, bis auf die Geschichte mit den Evictions. Da gibt es noch ein paar kleine Quarks. Aber ansonsten, man kann das komplett benutzen. Das komplette Portfolio mit Read-Through, Write-Through, Listener. Es ist alles da. Sämtliche Units, die gehen durch, bis auf die Evictions. Und auch die gehen September.
Immer. Das ist in unserem Kernprodukt drin. Wir werden die auf jeden Fall weiterbauen. Die Frage war,
wird das weiter gepflegt? Die Antwort lautet Ja, weil es in unserem Kernprodukt drin ist und weil dort wir zum Teil immer neue Anforderungen haben. Und daher ist allein schon unser Interesse, das zu machen. Aber abgesehen davon, das ganze Projekt ist schon seit einem Jahr
oder zwei Jahren auf GitHub vorhanden. Das heißt, wenn man da Sorgen hätte, da passiert vielleicht nichts mehr. Das ist keine Einbahnstraße. Und es ist natürlich auch noch so, wenn man jetzt wirklich sagt, jetzt ist wirklich End of Life, wenn das irgendwann mal sein sollte. Ich hoffe, das passiert nicht. Wenn man tatsächlich sagt,
ich mache JSA 107, es gibt immer Auswege. Außer für diese Spezialitäten, wie diese Verteilung, Expiration-Intervalle oder so, da könnte man vielleicht auch noch was implementieren. Es gibt immer Auswege. Und das ist auch das Schöne an JSA 107, dass es damit etwas einfacher wird.
Ich glaube, zuerst vorne. Die Frage war,
wie sieht das mit Spring aus? Die Antwort ist relativ einfach. Also von Tcache. Die Antwort ist dort relativ einfach. Tcache implementiert JSA 107. Spring unterstützt JSA 107. Als solches ist es halt an der Stelle unterstützt. Aber geht die Frage noch auf irgendwas anderes hin?
Sinnvollerweise genau die Frage war, in Spring
taucht Tcache noch nicht auf, aber es unterstützt. Das hat den Grund, weil Tcache noch nicht offiziell zertifiziert ist. Wahrscheinlich hat deswegen natürlich auch noch keiner getestet. Aktuell gibt es sechs Implementationen, die JSA 107 implementieren. Ich gehe davon aus, dass im September die Nummer 7 dazukommt. Ich bin da auch im Kontakt mit den entsprechenden
specification leads, Greg Luck, und auch einigen von den Expert-Members. Da bin ich in Kontakt. Und die haben einfach gesagt, sag uns Bescheid, wenn fertig ist, damit wir es aufnehmen können.
War diese Frage.
Das ist, denke ich, ziemliches Alleinstellungsmerkmal. Das habe ich bisher noch nirgends woanders gesehen. Und wir haben das halt gemacht, als wir bemerkt haben, wir haben da tatsächlich Probleme, so viel immer zu laden und kann man da nicht was machen. Es wäre erstaunlich, erfreulich einfach zu implementieren. Also das hat quasi überhaupt keine Auswirkungen gehabt. Das heißt, die Frage war
mit den Expiration-Intervallen, ob das jemand anders hat. Und wie gesagt, sonst keiner aktuell. Vielleicht kann man über JSA 107 irgendwas tricken mit den Expiration. Weil man kann auch eigene Klassen implementieren. Das ist noch nicht ganz klar. Genau das ist der Punkt, den wir uns aktuell angucken. Wie gesagt, das ist auch der letzte Punkt für den JSA 107, der noch zu machen ist.
Haben wir noch eine? Gut.
Die Metadaten. Genau. Die Frage war, wie groß ist der Overhead? Ich kann vom Caching, besonders da ja, diese Metadaten gespeichert werden. Jeder Caching muss das tun. Jeder hat Overhead. Ich kann einerseits natürlich verweisen
auf den Test, auf den Benchmark, der zeigt, wie der Speicherbedarf ist. Der ist besser als bei anderen. Ich kann natürlich auch konkret angeben. Also es gibt eine entsprechende Klasse, wo halt alles drin ist. Und die ist aktuell 48 Bytes groß.
Glaub ich. Gut, noch eine.
Zunächst, die Frage ist, ist T-Cache
auch so ähnlich einsetzbar wie Memcached. Ich kann das so zusammenfassen. Und zunächst mal die reine Imploration muss man dazu sagen, nein. Die Imploration selbst ist zunächst mal einfach Java. Jetzt ist es aber so, ich zeige mal ganz kurz noch mal einen der ersten Folien, die das vielleicht noch ein bisschen detaillierter beantworten
könnte. Und da hätten wir nämlich dann. Tcached ist ein reines Remding, ist Java. Und hier gibt es was, das sich nennt Tcached-Memcached. Das ist ein Tcached, der spricht Memcached-Protokoll. Das heißt ein Server, der über Jettie das Memcached-Protokoll spricht. Das heißt,
die Imploration in Jettie von einem Memcached-Protokoll existiert auch. Also im Prinzip kann man den auch als Remote-Server verwenden. Ist nicht gerade unser Hauptfokus? Aus der
Tcached-Memcached, weil Tcached sind halt Java-Klassen, da kommt man halt so nicht dran. Da muss man halt über irgendein Netzwerklayer gehen. Und das heißt, um es da zusammenzufassen, außerhalb von Java kann man bei Tcached nur auf das
Tcached-Memcached gehen und innerhalb kann man es auch direkt verwenden. Gut, ich glaube, ich sehe hier keine weiteren Fragen. Dann bedanke ich mich mal für die