Gegevenskompresje yn Apache Ignite. Sber syn ûnderfining

Gegevenskompresje yn Apache Ignite. Sber syn ûnderfiningBy it wurkjen mei grutte folumes fan gegevens kin soms it probleem fan gebrek oan skiifromte ûntstean. Ien manier om dit probleem op te lossen is kompresje, wêrtroch jo op deselde apparatuer kinne betelje om opslachvoluminten te fergrutsjen. Yn dit artikel sille wy sjen hoe't gegevenskompresje wurket yn Apache Ignite. Dit artikel sil allinich de skiifkompresjemetoaden beskriuwe dy't yn it produkt binne ymplementearre. Oare metoaden fan gegevenskompresje (oer it netwurk, yn it ûnthâld), al of net ymplementearre, sille bûten it berik bliuwe.

Dus, mei persistinsjemodus ynskeakele, as gefolch fan feroaringen yn gegevens yn 'e caches, begjint Ignite te skriuwen nei skiif:

  1. Ynhâld fan caches
  2. Write Ahead Log (hjirnei gewoan WAL)

D'r is al in skoft in meganisme foar WAL-kompresje, neamd WAL-kompresje. De koartlyn útbrochte Apache Ignite 2.8 yntrodusearre noch twa meganismen wêrmei jo gegevens op skiif kinne komprimearje: kompresje fan skiifpagina foar it komprimearjen fan de ynhâld fan caches en WAL-side-snapshot-kompresje foar it komprimearjen fan guon WAL-yngongen. Mear details oer alle trije fan dizze meganismen hjirûnder.

Skiif side kompresje

Hoe docht dit wurk

Litte wy earst in heul koarte blik nimme op hoe't Ignite gegevens opslacht. Side-ûnthâld wurdt brûkt foar opslach. De sidegrutte wurdt ynsteld oan it begjin fan 'e knooppunt en kin net feroare wurde yn lettere stadia; ek moat de sidegrutte in krêft fan twa wêze en in mearfâld fan 'e blokgrutte fan it bestânsysteem. Siden wurde laden yn RAM fan skiif as nedich; de grutte fan gegevens op skiif kin grutter wêze as it bedrach fan tawiisd RAM. As d'r net genôch romte is yn RAM om in side fan skiif te laden, wurde âlde, net mear brûkte siden út RAM ferwidere.

De gegevens wurde opslein op skiif yn 'e folgjende foarm: in apart bestân wurdt makke foar elke dieling fan elke cache-groep; yn dit bestân ferskine siden de iene nei de oare yn oprinnende yndeksfolchoarder. De folsleine side-identifikaasje befettet de cache-groep-identifikaasje, partitionnûmer en side-yndeks yn it bestân. Sa, mei help fan de folsleine side identifier, kinne wy ​​unyk bepale de triem en de offset yn it bestân foar elke side. Jo kinne mear lêze oer paging-ûnthâld yn it Apache Ignite Wiki-artikel: Ignite Persistent Store - ûnder de motorkap.

It kompresjemeganisme fan 'e skiifpagina, lykas jo miskien riede út' e namme, wurket op sidenivo. As dit meganisme ynskeakele is, wurde gegevens yn RAM ferwurke sa't it is, sûnder kompresje, mar as siden wurde bewarre fan RAM nei skiif, wurde se komprimearre.

Mar it komprimearjen fan elke side yndividueel is gjin oplossing foar it probleem; jo moatte op ien of oare manier de grutte fan 'e resultearjende gegevensbestannen ferminderje. As de sidegrutte net mear fêst is, kinne wy ​​gjin siden mear ien nei de oare skriuwe nei it bestân, om't dit in oantal problemen kin meitsje:

  • Mei de side-yndeks kinne wy ​​de offset net berekkenje wêrmei't it yn 'e triem leit.
  • It is net dúdlik wat te dwaan mei siden dy't net oan 'e ein fan' e triem en feroarje harren grutte. As de sidegrutte ôfnimt, ferdwynt de romte dy't it frijmakke. As de sidegrutte ferheget, moatte jo der in nij plak yn it bestân foar sykje.
  • As in side beweecht mei in oantal bytes dat net in mearfâld is fan 'e blokgrutte fan it bestânsysteem, dan sil it lêzen of skriuwen it nedich wêze om ien mear bestânsysteemblok oan te raken, wat kin liede ta prestaasjesdegradaasje.

Om foar te kommen it oplossen fan dizze problemen op syn eigen nivo, skiif side kompresje yn Apache Ignite brûkt in triem systeem meganisme neamd sparse triemmen. In sparse triem is ien wêryn guon nul-folle regio's kinne wurde markearre as "gaten". Yn dit gefal sille gjin bestânsysteemblokken wurde tawiisd om dizze gatten op te slaan, wat resulteart yn besparring op skiifromte.

It is logysk dat om in bestânsysteemblok te befrijen, de grutte fan it gat grutter of gelyk wêze moat oan it bestânsysteemblok, wat in ekstra beheining opleit op 'e sidegrutte en Apache Ignite: foar kompresje om effekt te hawwen, de sidegrutte moat strikt grutter wêze as de grutte fan it bestânsysteemblok. As de sidegrutte lyk is oan de blokgrutte, dan sille wy noait in inkeld blok frijmeitsje kinne, om't om ien blok frij te meitsjen, moat de komprimearre side 0 bytes besette. As de sidegrutte gelyk is oan de grutte fan 2 of 4 blokken, kinne wy ​​​​al op syn minst ien blok frijmeitsje as ús side komprimearre is nei respektivelik op syn minst 50% of 75%.

Sa is de definitive beskriuwing fan hoe't it meganisme wurket: By it skriuwen fan in side nei skiif wurdt besocht de side te komprimearjen. As de grutte fan 'e komprimearre side ien of mear bestânsysteemblokken frijlitte kin, dan wurdt de side yn komprimearre foarm skreaun, en wurdt in "gat" makke yn plak fan 'e befrijde blokken (in systeemoprop wurdt útfierd fallocate() mei de punch hole flagge). As de grutte fan 'e komprimearre side net tastean dat de blokken befrijd wurde, wurdt de side bewarre lykas is, net komprimearre. Alle side-offsets wurde op deselde manier berekkene as sûnder kompresje, troch de side-yndeks te fermannichfâldigjen mei de sidegrutte. Gjin ferhuzing fan siden is nedich op jo eigen. Side-offsets, krekt as sûnder kompresje, falle op 'e grinzen fan bestânsysteemblokken.

Gegevenskompresje yn Apache Ignite. Sber syn ûnderfining

Yn 'e hjoeddeistige ymplemintaasje kin Ignite allinich wurkje mei sparse bestannen ûnder Linux OS; dêrtroch kin kompresje fan skiifpagina's allinich ynskeakele wurde by it brûken fan Ignite op dit bestjoeringssysteem.

Kompresjealgoritmen dy't kinne wurde brûkt foar kompresje fan skiifpagina's: ZSTD, LZ4, Snappy. Dêrneist is der in bestjoeringssysteem modus (SKIP_GARBAGE), dêr't allinnich net brûkte romte op de side wurdt smiten út sûnder tapassen kompresje op de oerbleaune gegevens, dy't ferleget de lading op de CPU yn ferliking mei de earder neamde algoritmen.

Performance Impact

Spitigernôch haw ik gjin wurklike prestaasjesmjittingen útfierd op echte tribunes, om't wy dit meganisme net fan plan binne yn produksje te brûken, mar wy kinne teoretysk spekulearje wêr't wy sille ferlieze en wêr't wy sille winne.

Om dit te dwaan, moatte wy ûnthâlde hoe't siden wurde lêzen en skreaun as se tagong krije:

  • By it útfieren fan in lêsoperaasje wurdt it earst socht yn RAM; as it sykjen net slagget, wurdt de side yn RAM laden fan skiif troch deselde thread dy't it lêzen útfiert.
  • As in skriuwoperaasje wurdt útfierd, wurdt de side yn RAM markearre as smoarch, mar de side wurdt net fysyk bewarre op skiif fuortendaliks troch de tried dy't it skriuwen útfiert. Alle smoarge siden wurde letter yn it kontrôlepuntproses yn aparte diskusjes opslein op skiif.

Dat de ynfloed op lêsoperaasjes is:

  • Posityf (skiif IO), troch in fermindering fan it oantal lêzen triemsysteem blokken.
  • Negatyf (CPU), fanwege de ekstra lading dy't nedich is troch it bestjoeringssysteem om te wurkjen mei sparse bestannen. It is ek mooglik dat ekstra IO-operaasjes hjir ymplisyt ferskine om in kompleksere sparse triemstruktuer te bewarjen (spitigernôch bin ik net bekend mei alle details oer hoe sparse triemmen wurkje).
  • Negatyf (CPU), fanwege de needsaak om siden te dekomprimearjen.
  • D'r is gjin ynfloed op skriuwoperaasjes.
  • Ynfloed op it kontrôlepuntproses (alles hjir is fergelykber mei lêsoperaasjes):
  • Posityf (skiif IO), fanwege in fermindering fan it oantal skreaune triemsysteem blokken.
  • Negatyf (CPU, mooglik skiif IO), fanwege wurkjen mei sparse triemmen.
  • Negatyf (CPU), fanwege de needsaak foar sidekompresje.

Hokker kant fan 'e skaal sil de skaal tipje? Dit hinget allegear heul ôf fan 'e omjouwing, mar ik bin oanstriid om te leauwen dat kompresje fan skiifpagina's nei alle gedachten sil liede ta prestaasjesdegradaasje op de measte systemen. Boppedat litte tests op oare DBMS's dy't in ferlykbere oanpak brûke mei sparse bestannen in drop yn prestaasjes sjen as kompresje is ynskeakele.

Hoe ynskeakelje en konfigurearje

Lykas hjirboppe neamd, is de minimale ferzje fan Apache Ignite dy't kompresje fan skiifpagina's stipet 2.8 en allinich it Linux-bestjoeringssysteem wurdt stipe. Aktivearje en konfigurearje as folgjend:

  • D'r moat in ignite-kompresjemodule wêze yn it klassepaad. Standert leit it yn 'e Apache Ignite-distribúsje yn' e libs/opsjonele map en is net opnommen yn it klassepaad. Jo kinne de map gewoan ien nivo nei libs ferpleatse en dan as jo it útfiere fia ignite.sh sil it automatysk ynskeakele wurde.
  • Persistinsje moat ynskeakele wurde (ynskeakele fia DataRegionConfiguration.setPersistenceEnabled(true)).
  • De sidegrutte moat grutter wêze dan de blokgrutte fan it bestânsysteem (jo kinne it ynstelle mei DataStorageConfiguration.setPageSize() ).
  • Foar elke cache wêrfan de gegevens komprimearre wurde moatte, moatte jo de kompresjemetoade en (opsjoneel) it kompresjenivo (metoaden) ynstelle CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

WAL kompaktering

Hoe docht dit wurk

Wat is WAL en wêrom is it nedich? Hiel koart: dit is in log dat alle eveneminten befettet dy't úteinlik de side-opslach feroarje. It is foaral nedich om by in fal te herstellen te kinnen. Elke operaasje, foardat de brûker kontrôle jout, moat earst in evenemint opnimme yn WAL, sadat it yn gefal fan mislearring yn it log kin wurde ôfspield en alle operaasjes wersteld wêrop de brûker in súksesfol antwurd krige, sels as dizze operaasjes hie gjin tiid om te wjerspegeljen yn de side opslach op skiif (al hjirboppe It is beskreaun dat it eigentlike skriuwen nei de side winkel wurdt dien yn in proses neamd "checkpointing" mei wat fertraging troch aparte diskusjes).

Ynstjoerings yn WAL binne ferdield yn logysk en fysyk. Boolean binne de kaaien en wearden sels. Fysiek - wjerspegelet feroarings oan siden yn 'e sidewinkel. Wylst logyske records nuttich kinne wêze foar guon oare gefallen, binne fysike records allinich nedich foar herstel yn gefal fan in crash en records binne allinich nedich sûnt it lêste suksesfolle kontrôlepunt. Hjir sille wy net yn detail gean en útlizze wêrom't it op dizze manier wurket, mar belangstellenden kinne ferwize nei it al neamde artikel oer de Apache Ignite Wiki: Ignite Persistent Store - ûnder de motorkap.

D'r binne faak ferskate fysike records per logyske record. Dat is, bygelyks, ien set operaasje yn it cache beynfloedet ferskate siden yn side ûnthâld (in side mei de gegevens sels, siden mei yndeks, siden mei frije-listen). Yn guon syntetyske tests fûn ik dat fysike records oant 90% fan it WAL-bestân besette. Se binne lykwols foar in heul koarte tiid nedich (standert is it ynterval tusken kontrôlepunten 3 minuten). It soe logysk wêze om dizze gegevens kwyt te reitsjen nei it ferliezen fan har relevânsje. Dit is krekt wat it WAL-komprimeringsmeganisme docht: it makket fysike records kwyt en komprimearret de oerbleaune logyske records mei zip, wylst de triemgrutte heul signifikant wurdt fermindere (soms mei tsientallen kearen).

Fysiek bestiet WAL út ferskate segminten (standert 10) fan in fêste grutte (standert 64MB), dy't op in sirkulêre wize oerskreaun wurde. Sadree't it aktuele segmint ynfolle is, wurdt it folgjende segmint as aktueel tawiisd, en it ynfolle segmint wurdt troch in aparte tried nei it argyf kopiearre. WAL-kompaksje wurket al mei argyfsegminten. Ek, as in aparte tried, kontrolearret it de útfiering fan it kontrôlepunt en begjint kompresje yn argyfsegminten wêrfoar fysike records net mear nedich binne.

Gegevenskompresje yn Apache Ignite. Sber syn ûnderfining

Performance Impact

Sûnt WAL-kompaksje rint as in aparte tried, soe d'r gjin direkte ynfloed wêze moatte op 'e operaasjes dy't wurde útfierd. Mar it set noch altyd ekstra eftergrûnbelêsting op 'e CPU (kompresje) en skiif (lêze elk WAL-segmint út it argyf en skriuwt de komprimearre segminten), dus as it systeem op syn maksimale kapasiteit rint, sil it ek liede ta prestaasjesdegradaasje.

Hoe ynskeakelje en konfigurearje

Jo kinne WAL-ferdichting ynskeakelje mei it pân WalCompactionEnabled в DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Ek, mei help fan de metoade DataStorageConfiguration.setWalCompactionLevel (), kinne jo ynstelle it kompresje nivo as jo net tefreden binne mei de standert wearde (BEST_SPEED).

WAL side snapshot kompresje

Hoe docht dit wurk

Wy hawwe al fûn út dat yn WAL records wurde ferdield yn logyske en fysike. Foar elke feroaring oan elke side wurdt in fysyk WAL-record generearre yn sideûnthâld. Fysike records binne op syn beurt ek ferdield yn 2 subtypen: side-snapshot-record en delta-record. Elke kear as wy wat feroarje op in side en it oermeitsje fan in skjinne steat nei in smoarge steat, wurdt in folsleine kopy fan dizze side opslein yn WAL (side snapshot record). Sels as wy mar ien byte yn WAL feroare hawwe, sil it record wat grutter wêze as de sidegrutte. As wy wat feroarje op in al smoarge side, wurdt in delta-record foarme yn WAL, dy't allinich feroarings reflektearret yn ferliking mei de foarige steat fan 'e side, mar net de hiele side. Sûnt it weromsetten fan de tastân fan siden fan smoarch nei skjin wurdt útfierd tidens it kontrôlepuntproses, fuort nei it begjin fan it kontrôlepunt, sille hast alle fysike records allinich bestean út snapshots fan siden (om't alle siden direkt nei it begjin fan it kontrôlepunt skjin binne) , As wy it folgjende kontrôlepunt benaderje, begjint de delta-recordfraksje te groeien en opnij ynsteld oan it begjin fan it folgjende kontrôlepunt. Mjittingen yn guon syntetyske tests lieten sjen dat it oandiel fan side-snapshots yn it totale folume fan fysike records 90% berikt.

It idee fan WAL-side-snapshot-kompresje is om side-snapshots te komprimearjen mei in klearmakke side-kompresjeark (sjoch kompresje fan skiifpagina). Tagelyk, yn WAL, wurde records sequentieel opslein yn 'e modus allinich taheakje en d'r is gjin needsaak om records te binen oan' e grinzen fan blokken fan bestânsysteem, dus hjir, yn tsjinstelling ta it kompresjemeganisme fan 'e skiifpagina, hawwe wy gjin sparse bestannen nedich by allegear; dêrom sil dit meganisme net allinich wurkje op it OS Linux. Boppedat makket it ús net mear út hoefolle wy de side komprimearje koene. Sels as wy 1 byte befrijd hawwe, is dit al in posityf resultaat en kinne wy ​​​​komprimeare gegevens yn WAL bewarje, yn tsjinstelling ta kompresje fan skiifpagina's, wêr't wy de komprimearre side allinich bewarje as wy mear as 1 bestânsysteemblok befrijd hawwe.

Siden binne heul komprimerbere gegevens, har oandiel yn it totale WAL-volumint is heul heech, dus sûnder it WAL-bestânformaat te feroarjen kinne wy ​​​​in signifikante reduksje krije yn har grutte. Kompresje, ynklusyf logyske records, soe easkje in feroaring yn opmaak en ferlies fan komptabiliteit, Bygelyks, foar eksterne konsuminten dy't kin wêze ynteressearre yn logyske records, mar soe net liede ta in signifikante fermindering fan triemgrutte.

Lykas by kompresje fan skiifside, kin WAL-side-snapshot-kompresje ZSTD, LZ4, Snappy-kompresjealgoritmen brûke, lykas ek de SKIP_GARBAGE-modus.

Performance Impact

It is net dreech om te merken dat it direkt ynskeakeljen fan WAL-side-snapshot-kompresje allinich ynfloed hat op diskusjes dy't gegevens skriuwe nei side-ûnthâld, dat is dy diskusjes dy't gegevens yn caches feroarje. Lêzen fan fysike records út WAL komt mar ien kear, op it stuit de knooppunt wurdt ferhege nei in fal (en allinnich as it falt tidens in kontrôle).

Dit hat ynfloed op diskusjes dy't gegevens feroarje op de folgjende manier: wy krije in negatyf effekt (CPU) troch de needsaak om de side elke kear te komprimearjen foardat jo op skiif skriuwe, en in posityf effekt (skiif IO) troch in fermindering fan it bedrach fan gegevens skreaun. Hjirtroch is alles ienfâldich hjir: as de systeemprestaasjes wurdt beheind troch de CPU, krije wy in lichte degradaasje, as it wurdt beheind troch skiif I / O, krije wy in ferheging.

Yndirekt beynfloedet it ferminderjen fan de WAL-grutte ek (posityf) streamen dy't WAL-segminten dumpe yn it argyf en WAL-kompaksjestreamen.

Echte prestaasjestests yn ús omjouwing mei syntetyske gegevens lieten in lichte ferheging sjen (trochput ferhege mei 10% -15%, latency fermindere mei 10% -15%).

Hoe ynskeakelje en konfigurearje

Minimale Apache Ignite-ferzje: 2.8. Aktivearje en konfigurearje as folgjend:

  • D'r moat in ignite-kompresjemodule wêze yn it klassepaad. Standert leit it yn 'e Apache Ignite-distribúsje yn' e libs/opsjonele map en is net opnommen yn it klassepaad. Jo kinne de map gewoan ien nivo nei libs ferpleatse en dan as jo it útfiere fia ignite.sh sil it automatysk ynskeakele wurde.
  • Persistinsje moat ynskeakele wurde (ynskeakele fia DataRegionConfiguration.setPersistenceEnabled(true)).
  • De kompresjemodus moat ynsteld wurde mei de metoade DataStorageConfiguration.setWalPageCompression(), kompresje is standert útskeakele (útskeakele modus).
  • Opsjoneel kinne jo it kompresjenivo ynstelle mei de metoade DataStorageConfiguration.setWalPageCompression(), sjoch de javadoc foar de metoade foar jildige wearden foar elke modus.

konklúzje

De beskôge datakompresjemeganismen yn Apache Ignite kinne ûnôfhinklik fan elkoar brûkt wurde, mar elke kombinaasje dêrfan is ek akseptabel. As jo ​​​​begripe hoe't se wurkje, kinne jo bepale hoe geskikt se binne foar jo taken yn jo omjouwing en wat jo moatte opofferje as jo se brûke. Skiifside-kompresje is ûntworpen om de haadopslach te komprimearjen en kin in medium kompresjeferhâlding jaan. WAL-side-snapshot-kompresje sil in gemiddelde graad fan kompresje jaan foar WAL-bestannen, en sil nei alle gedachten sels prestaasjes ferbetterje. WAL-kompaksje sil gjin posityf effekt hawwe op prestaasjes, mar sil de grutte fan WAL-bestannen safolle mooglik ferminderje troch fysike records te ferwiderjen.

Boarne: www.habr.com

Add a comment