Úvod do kofeínu

1. Úvod

V tomto článku sa pozrieme na Kofeín - a vysokovýkonná kešovacia knižnica pre Java.

Jeden zásadný rozdiel medzi cache a a Mapa je to, že vyrovnávacia pamäť vysťahuje uložené položky.

An Politika vysťahovania rozhoduje o tom, ktoré objekty by sa mali vymazať kedykoľvek. Táto politika priamo ovplyvňuje mieru prístupov do pamäte cache - rozhodujúca vlastnosť kešovania knižníc.

Kofeín používa Okno TinyLfu politika vysťahovania, ktorá poskytuje a takmer optimálna miera úspešnosti.

2. Závislosť

Musíme pridať kofeín závislosť na našom pom.xml:

 com.github.ben-manes. kofeín kofeín 2.5.5 

Nájdete najnovšiu verziu servera kofeín na Maven Central.

3. Populačná vyrovnávacia pamäť

Zamerajme sa na kofeín tri stratégie pre populáciu cache: manuálne, synchrónne načítanie a asynchrónne načítanie.

Najprv napíšeme triedu pre typy hodnôt, ktoré uložíme do našej medzipamäte:

class DataObject {private final String data; private static int objectCounter = 0; // štandardné konštruktory / getre public static DataObject get (reťazcové dáta) {objectCounter ++; vrátiť nový DataObject (dáta); }}

3.1. Ručné vyplnenie

V tejto stratégii ručne vkladáme hodnoty do pamäte cache a získavame ich neskôr.

Inicializujme našu vyrovnávaciu pamäť:

Vyrovnávacia pamäť cache: Caffeine.newBuilder () .expireAfterWrite (1, TimeUnit.MINUTES) .maximumSize (100) .build ();

Teraz, môžeme získať určitú hodnotu z medzipamäte pomocou getIfPresent metóda. Táto metóda sa vráti nulový ak hodnota nie je prítomná v pamäti cache:

Kľúč reťazca = "A"; DataObject dataObject = cache.getIfPresent (kľúč); assertNull (dataObject);

Môžeme vyplniť vyrovnávaciu pamäť ručne pomocou dať metóda:

cache.put (kľúč, dataObject); dataObject = cache.getIfPresent (kľúč); assertNotNull (dataObject);

Hodnotu môžeme získať aj pomocou dostať metóda, ktorá trvá a Funkcia spolu s kľúčom ako argumentom. Táto funkcia sa použije na poskytnutie záložnej hodnoty, ak kľúč nie je prítomný v pamäti cache, ktorá by bola vložená do pamäte cache po výpočte:

dataObject = cache .get (kľúč, k -> DataObject.get ("Údaje pre A")); assertNotNull (dataObject); assertEquals ("Údaje pre A", dataObject.getData ());

The dostať metóda vykonáva výpočet atómovo. To znamená, že výpočet bude vykonaný iba raz - aj keď niekoľko vlákien žiada o hodnotu súčasne. Preto použitím dostať je lepšie ako getIfPresent.

Niekedy potrebujeme zneplatniť niektoré hodnoty z medzipamäte ručne:

cache.invalidate (kľúč); dataObject = cache.getIfPresent (kľúč); assertNull (dataObject);

3.2. Synchrónne načítanie

Tento spôsob načítania vyrovnávacej pamäte trvá a Funkcia, ktorý sa používa na inicializáciu hodnôt, podobne ako dostať metóda manuálnej stratégie. Pozrime sa, ako to môžeme využiť.

Najskôr musíme inicializovať našu cache:

LoadingCache cache = Caffeine.newBuilder () .maximumSize (100) .expireAfterWrite (1, TimeUnit.MINUTES) .build (k -> DataObject.get ("Údaje pre" + k));

Teraz môžeme načítať hodnoty pomocou dostať metóda:

DataObject dataObject = cache.get (kľúč); assertNotNull (dataObject); assertEquals ("Údaje pre" + kľúč, dataObject.getData ());

Množinu hodnôt môžeme získať aj pomocou získať všetko metóda:

Mapové dátaObjectMap = cache.getAll (Arrays.asList ("A", "B", "C")); assertEquals (3, dataObjectMap.size ());

Hodnoty sa získavajú z podkladovej back-endovej inicializácie Funkcia ktorý bol odovzdaný stavať metóda. To umožňuje použiť cache ako hlavnú fasádu pre prístup k hodnotám.

3.3. Asynchrónne načítanie

Táto stratégia funguje rovnako ako predchádzajúci, ale vykonáva operácie asynchrónne a vracia a CompletableFuture skutočná hodnota:

AsyncLoadingCache cache = Caffeine.newBuilder () .maximumSize (100) .expireAfterWrite (1, TimeUnit.MINUTES) .buildAsync (k -> DataObject.get ("Údaje pre" + k)));

Môžeme Použi dostať a získať všetko metódyrovnakým spôsobom, berúc do úvahy skutočnosť, že sa vrátia CompletableFuture:

Kľúč reťazca = "A"; cache.get (kľúč). potom Accept (dataObject -> {assertNotNull (dataObject); assertEquals ("Údaje pre" + kľúč, dataObject.getData ());}); cache.getAll (Arrays.asList ("A", "B", "C")) .thenAccept (dataObjectMap -> assertEquals (3, dataObjectMap.size ()));

CompletableFuture má bohaté a užitočné API, o ktorých sa viac dočítate v tomto článku.

4. Vysťahovanie hodnôt

Kofeín má tri stratégie pre vysťahovanie hodnoty: na základe veľkosti, času a referencie.

4.1. Vysťahovanie podľa veľkosti

Tento typ vysťahovania to predpokladá k vysťahovaniu dôjde, keď dôjde k prekročeniu nakonfigurovaného limitu veľkosti pamäte cache. Existujú dvoma spôsobmi získania veľkosti - počítanie objektov v pamäti cache alebo zisťovanie ich váhy.

Pozrime sa, ako by sme mohli počítať objekty v cache. Po inicializácii vyrovnávacej pamäte sa jej veľkosť rovná nule:

LoadingCache cache = Caffeine.newBuilder () .maximumSize (1) .build (k -> DataObject.get ("Údaje pre" + k)); assertEquals (0, cache.estimatedSize ());

Keď pridáme hodnotu, veľkosť sa zjavne zvýši:

cache.get ("A"); assertEquals (1, cache.estimatedSize ());

Do medzipamäte môžeme pridať druhú hodnotu, čo vedie k odstráneniu prvej hodnoty:

cache.get ("B"); cache.cleanUp (); assertEquals (1, cache.estimatedSize ());

Stojí za zmienku, že my zavolajte na vyčistiť pred získaním veľkosti pamäte cache. Je to tak preto, lebo vysťahovanie z vyrovnávacej pamäte sa vykonáva asynchrónne a táto metóda pomáha čakať na dokončenie vysťahovania.

Môžeme tiež zložiť a váhaFunkciaAk chcete získať veľkosť vyrovnávacej pamäte:

LoadingCache cache = Caffeine.newBuilder () .maximumWeight (10) .weigher ((k, v) -> 5) .build (k -> DataObject.get ("Údaje pre" + k)); assertEquals (0, cache.estimatedSize ()); cache.get ("A"); assertEquals (1, cache.estimatedSize ()); cache.get ("B"); assertEquals (2, cache.estimatedSize ());

Ak je váha vyššia ako 10, hodnoty sa odstránia z medzipamäte:

cache.get ("C"); cache.cleanUp (); assertEquals (2, cache.estimatedSize ());

4.2. Časové vysťahovanie

Táto stratégia vysťahovania je na základe doby expirácie záznamu a má tri typy:

  • Platnosť vyprší po prístupe - položka vypršala po uplynutí obdobia od posledného čítania alebo zápisu
  • Platnosť vyprší po písaní - položka vypršala po uplynutí obdobia od posledného zápisu
  • Vlastná politika - čas vypršania platnosti vypočítava pre každý záznam osobitne server Vypršanie platnosti implementácia

Nakonfigurujme stratégiu expire-after-access pomocou expireAfterAccess metóda:

LoadingCache cache = Caffeine.newBuilder () .expireAfterAccess (5, TimeUnit.MINUTES) .build (k -> DataObject.get ("Údaje pre" + k));

Na konfiguráciu stratégie expire-after-write používame expireAfterWrite metóda:

cache = Caffeine.newBuilder () .expireAfterWrite (10, TimeUnit.SECONDS) .weakKeys () .weakValues ​​() .build (k -> DataObject.get ("Údaje pre" + k));

Ak chcete inicializovať vlastnú politiku, musíme implementovať Vypršanie platnosti rozhranie:

cache = Caffeine.newBuilder (). expireAfter (nový Expiry () {@Override public long expireAfterCreate (reťazec, hodnota DataObject, long currentTime) {return value.getData (). length () * 1000;} @Override public long expireAfterUpdate (String key, DataObject value, long currentTime, long currentDuration) {return currentDuration;} @Override public long expireAfterRead (String key, DataObject value, long currentTime, long currentDuration) {return currentDuration;}}). Build (k -> DataObject .get ("Údaje pre" + k));

4.3. Referenčné vysťahovanie

Môžeme nakonfigurovať našu pamäť cache tak, aby umožňovala odpadkový zber kľúčov a / alebo hodnôt medzipamäte. Aby sme to dosiahli, nakonfigurovali by sme využitie WeakRefence pre kľúče aj hodnoty a môžeme nakonfigurovať SoftReference iba na zhromažďovanie hodnôt.

The WeakRefence použitie umožňuje zbieranie odpadkov z objektov, ak na objekt neexistujú silné odkazy. SoftReference umožňuje zbierať odpadky na základe globálnej stratégie JVM najmenej používanej naposledy. Viac podrobností o referenciách v Jave nájdete tu.

Mali by sme použiť Caffeine.weakKeys (), Caffeine.weakValues ​​(), a Caffeine.softValues ​​() na povolenie každej možnosti:

LoadingCache cache = Caffeine.newBuilder () .expireAfterWrite (10, TimeUnit.SECONDS) .weakKeys () .weakValues ​​() .build (k -> DataObject.get ("Data for" + k)); cache = Caffeine.newBuilder () .expireAfterWrite (10, TimeUnit.SECONDS) .softValues ​​() .build (k -> DataObject.get ("Údaje pre" + k));

5. Osviežujúci

Je možné nakonfigurovať vyrovnávaciu pamäť tak, aby automaticky obnovovala položky po stanovenom období. Pozrime sa, ako to urobiť pomocou refreshAfterWrite metóda:

Caffeine.newBuilder () .refreshAfterWrite (1, TimeUnit.MINUTES) .build (k -> DataObject.get ("Data for" + k));

Tu by sme mali pochopiť a rozdiel medzi expirovaťPo a refreshAfter. Keď sa požaduje záznam so skončenou platnosťou, vykonanie sa zablokuje, kým by zostavenie nevypočítalo novú hodnotu Funkcia.

Ale ak je položka vhodná na osvieženie, potom by vyrovnávacia pamäť vrátila starú hodnotu a asynchrónne znovu načítať hodnotu.

6. Štatistika

Kofeín má prostriedok zaznamenávanie štatistík o využití medzipamäte:

LoadingCache cache = Caffeine.newBuilder () .maximumSize (100) .recordStats () .build (k -> DataObject.get ("Údaje pre" + k)); cache.get ("A"); cache.get ("A"); assertEquals (1, cache.stats (). hitCount ()); assertEquals (1, cache.stats (). missCount ());

Môžeme tiež prejsť do recordStats dodávateľa, ktorý vytvára implementáciu StatsCounter. Tento objekt bude vložený s každou zmenou súvisiacou so štatistikou.

7. Záver

V tomto článku sme sa oboznámili s knižnicou Caffeine caching pre Java. Videli sme, ako nakonfigurovať a naplniť vyrovnávaciu pamäť, ako aj ako zvoliť vhodnú politiku vypršania platnosti alebo obnovenia podľa našich potrieb.

Tu zobrazený zdrojový kód je k dispozícii na serveri Github.


$config[zx-auto] not found$config[zx-overlay] not found