Een gids voor Apache Ignite

1. Inleiding

Apache Ignite is een open source geheugengericht gedistribueerd platform. We kunnen het gebruiken als een database, een caching-systeem of voor de gegevensverwerking in het geheugen.

Het platform gebruikt geheugen als opslaglaag en heeft daarom indrukwekkende prestaties. Simpel gezegd, dit is een van de snelste platforms voor atomaire gegevensverwerking die momenteel in gebruik zijn.

2. Installatie en configuratie

Bekijk om te beginnen de pagina 'Aan de slag' voor de eerste installatie- en installatie-instructies.

De Maven-afhankelijkheden voor de applicatie die we gaan bouwen:

 org.apache.ignite ignite-core $ {ignite.version} org.apache.ignite ignite-indexing $ {ignite.version} 

ontsteken-kern is de enige verplichte afhankelijkheid voor het project. Omdat we ook willen communiceren met de SQL, ontsteken-indexering is ook hier. $ {ignite.version} is de nieuwste versie van Apache Ignite.

Als laatste stap starten we het Ignite-knooppunt:

Ignite-knooppunt gestart OK (id = 53c77dea) Topologie-snapshot [ver = 1, servers = 1, clients = 0, CPU's = 4, offheap = 1,2 GB, heap = 1,0 GB] Gegevensregio's geconfigureerd: ^ - standaard [initSize = 256,0 MiB, maxSize = 1,2 GiB, persistenceEnabled = false]

De console-uitvoer hierboven laat zien dat we klaar zijn om te gaan.

3. Geheugenarchitectuur

Het platform is gebaseerd op Durable Memory Architecture. Dit maakt het mogelijk om de gegevens zowel op schijf als in het geheugen op te slaan en te verwerken. Het verhoogt de prestaties door de RAM-bronnen van het cluster effectief te gebruiken.

De gegevens in het geheugen en op de schijf hebben dezelfde binaire weergave. Dit betekent dat er geen extra conversie van de gegevens is tijdens het verplaatsen van de ene laag naar de andere.

Duurzame geheugenarchitectuur splitst zich op in blokken met een vaste grootte, genaamd pagina's. Pagina's worden buiten de Java-heap opgeslagen en in een RAM georganiseerd. Het heeft een unieke identificatie: FullPageId.

Pagina's communiceren met het geheugen met behulp van de PageMemory abstractie.

Het helpt om een ​​pagina te lezen, te schrijven en ook om een ​​pagina-ID toe te wijzen. In het geheugen associeert Ignite pagina's met Geheugenbuffers.

4. Geheugenpagina's

Een pagina kan de volgende statussen hebben:

  • Unloaded - er is geen paginabuffer in het geheugen geladen
  • Wissen - de paginabuffer wordt geladen en gesynchroniseerd met de gegevens op de schijf
  • Durty - de paginabuffer bevat gegevens die verschillen van die op de schijf
  • Vervuild in controlepunt - er is nog een wijziging die begint voordat de eerste op de schijf blijft staan. Hier begint een checkpoint en PageMemory houdt twee geheugenbuffers bij voor elke pagina.

Duurzaam geheugen wijst lokaal een geheugensegment toe met de naam Gegevensregio. Standaard heeft het een capaciteit van 20% van het clustergeheugen. Door de configuratie met meerdere regio's kunnen de bruikbare gegevens in een geheugen worden bewaard.

De maximale capaciteit van de regio is een geheugensegment. Het is een fysiek geheugen of een continue byte-array.

Om geheugenfragmentatie te voorkomen, bevat een enkele pagina meerdere sleutelwaarde-items. Elk nieuw item wordt toegevoegd aan de meest optimale pagina. Als de grootte van het sleutel-waardepaar de maximale capaciteit van de pagina overschrijdt, slaat Ignite de gegevens op meer dan één pagina op. Dezelfde logica is van toepassing op het bijwerken van de gegevens.

SQL- en cache-indexen worden opgeslagen in structuren die bekend staan ​​als B + Trees. Cache-sleutels zijn gerangschikt op hun sleutelwaarden.

5. Levenscyclus

Elk Ignite-knooppunt wordt op één JVM-instantie uitgevoerd. Het is echter mogelijk om te configureren dat meerdere Ignite-knooppunten in één JVM-proces worden uitgevoerd.

Laten we de soorten levenscyclusgebeurtenissen doornemen:

  • BEFORE_NODE_START - voordat het Ignite-knooppunt wordt opgestart
  • AFTER_NODE_START - vuurt net nadat het Ignite-knooppunt is gestart
  • BEFORE_NODE_STOP - voordat u de knooppuntstop start
  • AFTER_NODE_STOP - nadat het Ignite-knooppunt stopt

Om een ​​standaard Ignite-knooppunt te starten:

Ignite ignite = Ignition.start ();

Of vanuit een configuratiebestand:

Ignite ignite = Ignition.start ("config / example-cache.xml");

Als we meer controle over het initialisatieproces nodig hebben, is er een andere manier met behulp van Levenscyclus Bean koppel:

openbare klasse CustomLifecycleBean implementeert LifecycleBean {@Override public void onLifecycleEvent (LifecycleEventType lifecycleEventType) gooit IgniteException {if (lifecycleEventType == LifecycleEventType.AFTER_NODE_START) {// ...}}}

Hier kunnen we de typen levenscyclusgebeurtenissen gebruiken om acties uit te voeren voor of nadat het knooppunt start / stopt.

Voor dat doel geven we de configuratie-instantie door met de CustomLifecycleBean naar de startmethode:

IgniteConfiguration-configuratie = nieuwe IgniteConfiguration (); configuration.setLifecycleBeans (nieuwe CustomLifecycleBean ()); Ignite ignite = Ignition.start (configuratie);

6. Gegevensraster in het geheugen

Ignite-gegevensraster is een gedistribueerde opslag van sleutelwaarden, erg bekend bij gepartitioneerd Hash kaart. Het is horizontaal geschaald. Dit betekent dat we meer clusterknooppunten toevoegen en dat er meer gegevens in het cachegeheugen worden opgeslagen of in het geheugen worden opgeslagen.

Het kan aanzienlijke prestatieverbetering bieden aan software van derden, zoals NoSql, RDMS-databases als een extra laag voor caching.

6.1. Ondersteuning voor caching

De gegevenstoegang-API is gebaseerd op de JCache JSR 107-specificatie.

Laten we als voorbeeld een cache maken met behulp van een sjabloonconfiguratie:

IgniteCache cache = ignite.getOrCreateCache ("baeldingCache");

Laten we eens kijken wat er hier gebeurt voor meer details. Eerst zoekt Ignite het geheugengebied waar de cache is opgeslagen.

Vervolgens wordt de B + boomindexpagina gelokaliseerd op basis van de sleutel-hashcode. Als de index bestaat, wordt een gegevenspagina van de bijbehorende sleutel gelokaliseerd.

Als de index NULL is, maakt het platform de nieuwe gegevensinvoer met behulp van de opgegeven sleutel.

Laten we vervolgens wat toevoegen Werknemer voorwerpen:

cache.put (1, nieuwe werknemer (1, "John", true)); cache.put (2, nieuwe medewerker (2, "Anna", false)); cache.put (3, nieuwe werknemer (3, "George", true));

Nogmaals, het duurzame geheugen zoekt naar het geheugengebied waar de cache thuishoort. Op basis van de cachesleutel wordt de indexpagina in een B + -boomstructuur geplaatst.

Als de indexpagina niet bestaat, wordt er een nieuwe aangevraagd en aan de stamboom toegevoegd.

Vervolgens wordt een gegevenspagina toegewezen aan de indexpagina.

Om de medewerker uit de cache te lezen, gebruiken we gewoon de sleutelwaarde:

Medewerker medewerker = cache.get (1);

6.2. Streaming-ondersteuning

Datastreaming in het geheugen biedt een alternatieve benadering voor de gegevensverwerkingstoepassingen op basis van schijf en bestandssysteem. De streaming-API splitst de gegevensstroom met hoge belasting op in meerdere fasen en routeert deze voor verwerking.

We kunnen ons voorbeeld aanpassen en de gegevens uit het bestand streamen. Eerst definiëren we een datastreamer:

IgniteDataStreamer streamer = ignite .dataStreamer (cache.getName ());

Vervolgens kunnen we een stroomtransformator registreren om de ontvangen werknemers als werknemer te markeren:

streamer.receiver (StreamTransformer.from ((e, arg) -> {Werknemer werknemer = e.getValue (); werknemer.setEmployed (true); e.setValue (werknemer); terugkeer werknemer;}));

Als laatste stap herhalen we de medewerkers.txt bestandsregels en converteer ze naar Java-objecten:

Padpad = Paths.get (IgniteStream.class.getResource ("workers.txt") .toURI ()); Gson gson = nieuwe Gson (); Files.lines (pad) .forEach (l -> streamer.addData (employee.getId (), gson.fromJson (l, Employee.class)));

Met gebruik van streamer.addData () zet de werknemer objecten in de stroom.

7. SQL-ondersteuning

Het platform biedt een geheugencentrische, fouttolerante SQL-database.

We kunnen verbinding maken met pure SQL API of met JDBC. De SQL-syntaxis is hier ANSI-99, dus alle standaardaggregatiefuncties in de query's, DML, DDL-taalbewerkingen worden ondersteund.

7.1. JDBC

Laten we voor meer praktische zaken een tabel met werknemers maken en er wat gegevens aan toevoegen.

Met dat doel, we registreren een JDBC-stuurprogramma en openen een verbinding als volgende stap:

Class.forName ("org.apache.ignite.IgniteJdbcThinDriver"); Connection conn = DriverManager.getConnection ("jdbc: ignite: thin: //127.0.0.1/");

Met behulp van de standaard DDL-opdracht vullen we de Werknemer tafel:

sql.executeUpdate ("CREATE TABLE Employee (" + "id LANGE PRIMAIRE SLEUTEL, naam VARCHAR, isEmployed tinyint (1))" + "MET \" sjabloon = gerepliceerd \ "");

Na het WITH-sleutelwoord kunnen we de cacheconfiguratiesjabloon instellen. Hier gebruiken we de REPLICATED. Standaard is de sjabloonmodus GEPARTITIONEERD. Om het aantal exemplaren van de gegevens te specificeren, kunnen we ook specificeren BACK-UPS parameter hier, wat standaard 0 is.

Laten we vervolgens wat gegevens optellen met behulp van de INSERT DML-instructie:

PreparedStatement sql = conn.prepareStatement ("INVOEGEN IN Werknemer (id, naam, isEmployed) WAARDEN (?,?,?)"); sql.setLong (1, 1); sql.setString (2, "James"); sql.setBoolean (3, true); sql.executeUpdate (); // voeg de rest toe 

Daarna selecteren we de records:

ResultSet rs = sql.executeQuery ("SELECT e.name, e.isEmployed" + "FROM Employee e" + "WHERE e.isEmployed = TRUE")

7.2. Vraag de objecten

Het is ook mogelijk om een ​​query uit te voeren op Java-objecten die in de cache zijn opgeslagen. Ignite behandelt het Java-object als een afzonderlijk SQL-record:

IgniteCache cache = ignite.cache ("baeldungCache"); SqlFieldsQuery sql = nieuwe SqlFieldsQuery ("selecteer naam van werknemer waar isEmployed = 'true'"); QueryCursor cursor = cache.query (sql); for (List row: cursor) {// doe iets met de rij}

8. Samenvatting

In deze tutorial hebben we het Apache Ignite-project kort bekeken. Deze gids belicht de voordelen van het platform ten opzichte van andere vergelijkbare producten, zoals prestatieverbeteringen, duurzaamheid en lichtgewicht API's.

Als resultaat, we hebben geleerd hoe we de SQL-taal en Java API kunnen gebruiken om de gegevens op te slaan, op te halen en te streamen in het persistentie- of in-memory-raster.

Zoals gewoonlijk is de volledige code voor dit artikel beschikbaar op GitHub.