Key Value Store met Chronicle Map

1. Overzicht

In deze tutorial gaan we zien hoe we de Chronicle Map kunnen gebruiken voor het opslaan van sleutel-waardeparen. We zullen ook korte voorbeelden maken om het gedrag en het gebruik ervan te demonstreren.

2. Wat is een kroniekkaart?

Volgens de documentatie, "Chronicle Map is een supersnelle, niet-blokkerende sleutelwaardeopslag in het geheugen, ontworpen voor toepassingen met lage latentie en / of meerdere processen".

Kortom, het is een off-heap key-value store. De kaart heeft niet veel RAM nodig om goed te kunnen functioneren. Het kan groeien op basis van de beschikbare schijfcapaciteit. Bovendien ondersteunt het de replicatie van de gegevens in een multi-master serveropstelling.

Laten we nu kijken hoe we het kunnen opzetten en ermee kunnen werken.

3. Maven Afhankelijkheid

Om te beginnen, moeten we de afhankelijkheid van de kroniekkaart aan ons project toevoegen:

 net.openhft chronicle-map 3.17.2 

4. Soorten Chronicle Map

We kunnen een kaart op twee manieren maken: ofwel als een kaart in het geheugen of als een permanente kaart.

Laten we beide in detail bekijken.

4.1. In-Memory-kaart

Een Chronicle Map in het geheugen is een kaartarchief dat wordt aangemaakt in het fysieke geheugen van de server. Dit betekent het is alleen toegankelijk binnen het JVM-proces waarin de kaartopslag is gemaakt.

Laten we een snel voorbeeld bekijken:

ChronicleMap inMemoryCountryMap = ChronicleMap .of (LongValue.class, CharSequence.class) .name ("landkaart") .entries (50) .averageValue ("Amerika") .create ();

Om het eenvoudig te houden, maken we een kaart met 50 land-ID's en hun namen. Zoals we in het codefragment kunnen zien, is het maken vrij eenvoudig, behalve het gemiddelde waarde() configuratie. Dit vertelt de kaart om het gemiddelde aantal bytes te configureren dat wordt ingenomen door kaartinvoerwaarden.

Met andere woorden, Bij het maken van de kaart bepaalt de Chronicle Map het gemiddelde aantal bytes dat wordt ingenomen door de geserialiseerde vorm van waarden. Het doet dit door de gegeven gemiddelde waarde te serialiseren met behulp van de geconfigureerde waarde-marshallers. Het wijst dan het bepaalde aantal bytes toe voor de waarde van elk kaartitem.

Een ding dat we moeten opmerken als het gaat om de in-memory map, is dat de gegevens alleen toegankelijk zijn als het JVM-proces actief is. De bibliotheek zal de gegevens wissen wanneer het proces wordt beëindigd.

4.2. Aanhoudende kaart

In tegenstelling tot een in-memory map, de implementatie zal een persistente kaart op schijf opslaan. Laten we nu kijken hoe we een persistente kaart kunnen maken:

ChronicleMap persistedCountryMap = ChronicleMap .of (LongValue.class, CharSequence.class) .name ("country-map") .entries (50) .averageValue ("America") .createPersistedTo (nieuw bestand (System.getProperty ("user.home ") +" /country-details.dat "));

Hierdoor wordt een bestand gemaakt met de naam country-details.dat in de opgegeven map. Als dit bestand al beschikbaar is in het opgegeven pad, opent de bouwer-implementatie een link naar de bestaande datastore vanuit dit JVM-proces.

We kunnen gebruik maken van de persistente kaart in gevallen waarin we willen dat deze:

  • overleven voorbij het scheppingsproces; bijvoorbeeld ter ondersteuning van herimplementatie van hete applicaties
  • maak het globaal op een server; bijvoorbeeld om meerdere gelijktijdige procestoegang te ondersteunen
  • fungeren als een gegevensopslag die we op de schijf zullen opslaan

5. Maatconfiguratie

Het is verplicht om de gemiddelde waarde en de gemiddelde sleutel te configureren tijdens het maken van een Chronicle Map, behalve in het geval dat ons sleutel / waardetype een primitieve of een waarde-interface is. In ons voorbeeld configureren we niet de gemiddelde sleutel sinds het sleuteltype LongValue is een waarde-interface.

Laten we nu eens kijken wat de opties zijn voor het configureren van het gemiddelde aantal sleutel- / waardebytes:

  • gemiddelde waarde() - De waarde waaruit het gemiddelde aantal bytes dat moet worden toegewezen voor de waarde van een kaartitem, wordt bepaald
  • gemiddeldeValueSize () - Het gemiddelde aantal bytes dat moet worden toegewezen voor de waarde van een kaartvermelding
  • constantValueSizeBySample () - Het aantal bytes dat moet worden toegewezen voor de waarde van een kaartitem wanneer de grootte van de waarde altijd hetzelfde is
  • gemiddeldeKey () - De sleutel waaruit het gemiddelde aantal bytes wordt bepaald dat moet worden toegewezen aan de sleutel van een kaartitem
  • gemiddeldeKeySize () - Het gemiddelde aantal bytes dat moet worden toegewezen aan de sleutel van een kaartitem
  • constantKeySizeBySample () - Het aantal bytes dat moet worden toegewezen aan de sleutel van een kaartvermelding wanneer de grootte van de sleutel altijd hetzelfde is

6. Sleutel- en waardetypen

Er zijn bepaalde normen die we moeten volgen bij het maken van een Chronicle Map, vooral bij het definiëren van de sleutel en waarde. De kaart werkt het beste wanneer we de sleutel en waarde maken met behulp van de aanbevolen typen.

Hier zijn enkele van de aanbevolen soorten:

  • Waarde interfaces
  • Elke klasse die implementeert Byteable interface van Chronicle Bytes
  • Elke klasse die implementeert Bytes Onderscheidbaar interface van Chronicle Bytes; de implementatieklasse moet een openbare no-arg constructor hebben
  • byte[] en ByteBuffer
  • CharSequence, Draad, en StringBuilder
  • Geheel getal, Lang, en Dubbele
  • Elke klasse die implementeert java.io.Externalizable; de implementatieklasse moet een openbare no-arg constructor hebben
  • Elk type implementatie java.io.Serializable, inclusief omkaderde primitieve typen (behalve degene die hierboven zijn vermeld) en array-typen
  • Elk ander type, als aangepaste serialisatoren worden geleverd

7. Een Chronicle Map opvragen

Chronicle Map ondersteunt zowel single-key queries als multi-key queries.

7.1. Enkele sleutelquery's

Query's met één sleutel zijn de bewerkingen die betrekking hebben op één enkele sleutel. ChronicleMap ondersteunt alle bewerkingen van Java Kaart interface en ConcurrentMap koppel:

LongValue qatarKey = Values.newHeapInstance (LongValue.class); qatarKey.setValue (1); inMemoryCountryMap.put (qatarKey, "Qatar"); // ... CharSequence country = inMemoryCountryMap.get (sleutel);

Naast de normale ophaal- en plaatsbewerkingen, ChronicleMap voegt een speciale bewerking toe, getUsing (), dat de geheugenvoetafdruk verkleint tijdens het ophalen en verwerken van een invoer. Laten we dit in actie zien:

LongValue-sleutel = Values.newHeapInstance (LongValue.class); StringBuilder country = nieuwe StringBuilder (); key.setValue (1); persistedCountryMap.getUsing (sleutel, land); assertThat (country.toString (), is (equalTo ("Romania"))); key.setValue (2); persistedCountryMap.getUsing (sleutel, land); assertThat (country.toString (), is (equalTo ("India")));

Hier hebben we hetzelfde gebruikt StringBuilder object voor het ophalen van waarden van verschillende sleutels door deze door te geven aan de getUsing () methode. Het hergebruikt in feite hetzelfde object om verschillende items op te halen. In ons geval is de getUsing () methode is gelijk aan:

country.setLength (0); country.append (persistedCountryMap.get (key));

7.2. Multi-Key Query's

Er kunnen gebruiksscenario's zijn waarbij we met meerdere sleutels tegelijk te maken hebben. Hiervoor kunnen we de queryContext () functionaliteit. De queryContext () methode zal een context creëren voor het werken met een kaartitem.

Laten we eerst een multimap maken en er enkele waarden aan toevoegen:

Set averageValue = IntStream.of (1, 2) .boxed (). Collect (Collectors.toSet ()); ChronicleMap multiMap = ChronicleMap .of (Integer.class, (Class) (Class) Set.class) .name ("multi-map") .entries (50) .averageValue (averageValue) .create (); Set set1 = nieuwe HashSet (); set1.add (1); set1.add (2); multiMap.put (1, set1); Set2 = nieuwe HashSet (); set2.add (3); multiMap.put (2, set2);

Om met meerdere vermeldingen te werken, moeten we die vermeldingen vergrendelen om inconsistentie te voorkomen die kan optreden als gevolg van een gelijktijdige update:

probeer (ExternalMapQueryContext var13 -> fistContext = multiMap.queryContext (1)) {probeer (ExternalMapQueryContext var13 -> secondContext = multiMap.queryContext (2)) {fistContext.updateLock (). lock (); secondContext.updateLock (). lock (); MapEntry firstEntry = fistContext.entry (); Stel firstSet = firstEntry.value (). Get (); firstSet.remove (2); MapEntry secondEntry = secondContext.entry (); Stel secondSet = secondEntry.value (). Get (); secondSet.add (4); firstEntry.doReplaceValue (fistContext.wrapValueAsData (firstSet)); secondEntry.doReplaceValue (secondContext.wrapValueAsData (secondSet)); }} eindelijk {assertThat (multiMap.get (1) .size (), is (equalTo (1))); assertThat (multiMap.get (2) .size (), is (equalTo (2))); }

8. De kroniekkaart sluiten

Nu we klaar zijn met het werken met onze kaarten, laten we het dichtbij() methode op onze kaartobjecten om het off-heap-geheugen en de bijbehorende bronnen vrij te geven:

persistedCountryMap.close (); inMemoryCountryMap.close (); multiMap.close ();

Een ding om in gedachten te houden is dat alle kaartbewerkingen moeten worden voltooid voordat de kaart wordt gesloten. Anders kan de JVM onverwachts crashen.

9. Conclusie

In deze tutorial hebben we geleerd hoe we een Chronicle Map kunnen gebruiken om sleutel-waardeparen op te slaan en op te halen. Hoewel de communityversie beschikbaar is met de meeste kernfunctionaliteiten, heeft de commerciële versie een aantal geavanceerde functies, zoals gegevensreplicatie over meerdere servers en externe oproepen.

Alle voorbeelden die we hier hebben besproken, zijn te vinden in het Github-project.


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