Data compression in Apache Ignite. Experience of Sber

Data compression in Apache Ignite. Experience of SberPri práci s veľkými objemami dát môže nastať problém nedostatku miesta na diskoch. Jedným z riešení tohto problému je kompresia, ktorá umožňuje na rovnakom zariadení zvýšiť objemy úložiska. V tomto článku sa pozrieme na to, ako funguje kompresia dát v Apache Ignite. V článku budú opísané len spôsoby kompresie implementované v rámci produktu. Iné spôsoby kompresie dát (cez sieť, v pamäti), či už realizované alebo nie, zostanú mimo našich úvah.

Takže pri zapnutom režime persistence, v dôsledku zmien dát v kešoch, Ignite začne zapisovať na disk:

  1. Obsah kešov
  2. Záznamový denník predbežného zápisu (Write Ahead Log, ďalej len WAL)

Pre kompresiu WAL už existuje mechanizmus, ktorý sa nazýva WAL compaction. V nedávno vydanom Apache Ignite 2.8 pribudli ďalšie dva mechanizmy umožňujúce kompresiu dát na disku, a to disk page compression pre kompresiu obsahu kešov a WAL page snapshot compression pre kompresiu niektorých záznamov WAL. Viac o všetkých týchto troch mechanizmoch nájdete nižšie.

Disk page compression

Ako to funguje

Na začiatok si veľmi stručne povieme, ako Ignite uchováva dáta. Na uchovávanie sa používa stránková pamäť. Veľkosť stránky je stanovená pri spustení uzla a nemôže byť zmenená v neskorších fázach, takisto musí byť veľkosť stránky mocninou dvoch a násobkom veľkosti bloku súborového systému. Stránky sa načítavajú do RAM z disku podľa potreby, pričom veľkosť dát na disku môže presahovať objem vyhradenej RAM. V prípade nedostatku miesta v RAM na načítanie stránky z disku budú staršie, už nepoužívané stránky vytlačené z RAM.

Na disku sa dáta uchovávajú nasledujúcim spôsobom: pre každú partíciu každej kešovej skupiny sa vytvára samostatný súbor, v tomto súbore, v poradí vzostupne podľa indexu, nasledujú stránky. Celkový identifikátor stránky obsahuje identifikátor kešovej skupiny, číslo partície a index stránky v súbore. Týmto spôsobom môžeme podľa celkového identifikátora stránky jednoznačne určiť súbor a offset v súbore pre každú stránku. Podrobnejšie informácie o fungovaní stránkovej pamäte môžete nájsť v článku na Apache Ignite Wiki: Ignite Persistent Store — pod kapotou.

Mechaniz diskovej kompresie stránok, ako naznačuje názov, pracuje na úrovni stránok. Pri zapnutí tohto mechanizmu sa práca s údajmi v RAM vykonáva bez akýchkoľvek kompresií, avšak v momente ukladania stránok z RAM na disk sa vykonáva ich kompresia.

Ale zmenšiť každú stránku zvlášť nie je ešte riešením problému, je potrebné nejakým spôsobom zmenšiť veľkosť konečných súborov s údajmi. Ak prestane byť veľkosť stránky pevným číslom, už nemôžeme zapisovať stránky do súboru jednu po druhej, pretože to môže spôsobiť celú radu problémov:

  • Nebudeme môcť pomocou indexu stránky vypočítať offset, na ktorom sa nachádza v súbore.
  • Nie je jasné, čo robiť so stránkami, ktoré sa nachádzajú nie na konci súboru a menia svoju veľkosť. Ak sa veľkosť stránky zmenší, miesto, ktoré uvoľnila, zmizne. Ak sa veľkosť stránky zvýši, pre ňu bude potrebné hľadať už nové miesto v súbore.
  • Ak sa stránka posunie na počet bajtov, ktorý nie je násobkom veľkosti bloku súborového systému, na jej čítanie alebo zápis bude potrebné zasiahnuť o jeden blok súborového systému viac, čo môže spôsobiť zhoršenie výkonu.

Aby sa tieto problémy nemuseli riešiť na svojej úrovni, disková kompresia stránok v Apache Ignite využíva mechanizmus súborového systému nazvaný sparse súbory. Sparse (riedky) súbor je taký súbor, v ktorom niektoré regióny vyplnené nulami môžu byť označené ako „díry“. V tomto prípade nebude pre tieto díry vyhradených žiadne bloky súborového systému, čo vedie k úspore miesta na disku.

Je logické, že na uvoľnenie bloku súborového systému musí byť veľkosť díry väčšia alebo rovná bloku súborového systému, čo ukladať dodatočné obmedzenie na veľkosť stránky v Apache Ignite: aby kompresia mala nejaký efekt, musí byť veľkosť stránky prísne väčšia ako veľkosť bloku súborového systému. Ak bude veľkosť stránky rovná veľkosti bloku, nikdy nebudeme môcť uvoľniť ani jeden blok, pretože na uvoľnenie jediného bloku musí zmenšená stránka zaberat 0 bajtov. Ak bude veľkosť stránky rovná veľkosti 2 alebo 4 blokov, už môžeme uvoľniť aspoň jeden blok, ak sa naša stránka zmenší minimálne na 50% alebo na 75% príslušne.

Takže konečné popisovanie fungovania mechanizmu: Pri zapisovaní stránky na disk sa pokúsi stránku komprimovať. Ak veľkosť komprimovanej stránky umožňuje uvoľniť jeden alebo viac blokov súborového systému, stránka sa zapisuje v komprimovanej forme, na mieste uvoľnených blokov sa vytvorí „diera“ (vykoná sa systémový volanie s praporkom „punch hole"). fallocate() Ak veľkosť komprimovanej stránky neumožňuje uvoľniť bloky, stránka sa uloží tak, ako je, v nekomprimovanej forme. Všetky ofsety stránok sa počítajú rovnako ako bez kompresie, násobením indexu stránky rozmerom stránky. Žiadna relokácia stránok nie je potrebná. Ofsety stránok, ako aj bez kompresie, sa dostávajú na hranice blokov súborového systému.

Data compression in Apache Ignite. Experience of Sber

V súčasnej implementácii dokáže Ignite pracovať so sparse súbormi len pod operačným systémom Linux; preto môže byť disková kompresia strán zapnutá len pri používaní Ignite na tomto operačnom systéme.

Algoritmy kompresie, ktoré môžu byť použité pre diskovú kompresiu strán: ZSTD, LZ4, Snappy. Navyše existuje režim prevádzky (SKIP_GARBAGE), pri ktorom sa len vyhodí nepoužívané miesto na stránke bez použitia kompresie na zostávajúcich údajoch, čo umožňuje znížiť zaťaženie CPU v porovnaní s predtým uvedenými algoritmami.

Vplyv na výkon

Žiaľ, skutočné meranie výkonu na reálnych testovacích staniciach som nevykonal, pretože neplánujeme používať tento mechanizmus v produkcii, ale môžeme teoretizovať, kde stratíme a kde ziskáme.

Aby sme to mohli zvážiť, musíme si pripomenúť, ako sa vykonáva čítanie a písanie strán pri ich prístupe:

  • Pri vykonávaní operácie čítania sa najprv vyhľadá v RAM, ak hľadanie zlyhá, stránka sa načíta do RAM z disku rovnakým vláknom, ktoré vykonáva čítanie.
  • Pri vykonávaní operácie písania sa stránka v RAM označí ako špinavá, pričom fyzické uloženie stránky na disk sa ihneď v toku, ktorý vykonáva zapisovanie, nevykonáva. Všetky špinavé stránky sa uložia na disk neskôr počas procesu checkpointu prostredníctvom samostatných vlákien.

Takže vplyv na operácie čítania:

  • Pozitívny (disk IO), vďaka zníženiu počtu čítaných blokov súborového systému.
  • Negatívny (CPU), kvôli dodatočnej záťaži potrebnej pre operačný systém, aby mohol pracovať so sparse súbormi. Rovnako je možné, že sa tu implicitne objavia dodatočné IO operácie na uloženie zložitejšej štruktúry sparse súboru (so všetkými detailmi funkcie sparse súborov, žiaľ, nie som oboznámený).
  • Negatívny (CPU), kvôli potrebe dekompresie strán.
  • Vplyv na zápisové operácie nie je.
  • Vplyv na proces checkpointu (tu je to všetko podobné ako pri čítacích operáciách):
  • Pozitívny (disk IO), kvôli zníženému počtu zapísaných blokov súborového systému.
  • Negatívny (CPU, možno disk IO), kvôli práci so sparse súbormi.
  • Negatívny (CPU), kvôli potrebe kompresie strán.

Ktorá strana sa prepočíta? Všetko veľmi závisí od prostredia, ale naklonený som k tomu, že kompresia diskových strán pravdepodobne povedie k degradácii výkonu na väčšine systémov. O to viac, že testy na iných DBMS, ktoré používajú podobný prístup so sparse súbormi, ukazujú pokles výkonu pri zapnutej kompresii.

Ako zapnúť a nastaviť

Ako už bolo uvedené vyššie, minimálna verzia Apache Ignite, ktorá podporuje kompresiu diskových strán: 2.8 a je podporovaná iba operačným systémom Linux. Zapnutie a nastavenie sa vykonáva nasledovne:

  • V class-path by mal byť modul ignite-compression. Predvolene sa nachádza v distribúcii Apache Ignite v adresári libs/optional a nie je zahrnutý v class-path. Jednoducho môžete presunúť adresár o jeden level vyššie do libs a pri spustení cez ignite.sh bude automaticky zahrnutý.
  • Trvalosť musí byť zapnutá (zapína sa cez DataRegionConfiguration.setPersistenceEnabled(true)).
  • Veľkosť stránky musí byť väčšia ako veľkosť bloku súborového systému (možno nastaviť pomocou DataStorageConfiguration.setPageSize() ).
  • Pre každý cache, ktorého dáta je potrebné komprimovať, je nutné v konfigurácii nastaviť metódu kompresie a (voliteľne) úroveň kompresie (metódy CacheConfiguration.setDiskPageCompression(), CacheConfiguration.setDiskPageCompressionLevel()).

WAL kompresia

Ako to funguje

Čo je WAL a na čo je potrebný? Veľmi stručne: je to žurnál, do ktorého sa zapisujú všetky udalosti, ktoré nakoniec menia stránkové úložisko. Potrebný je predovšetkým na možnosť obnovy v prípade pádu. Každá operácia, skôr než odovzdá kontrolu užívateľovi, by mala najprv zapísať udalosti do WAL, aby v prípade pádu mohla tieto udalosti prehrávať z žurnálu a obnoviť všetky operácie, pri ktorých užívateľ dostal úspešnú odpoveď, aj keď tieto operácie sa ešte nestihli odraziť v stránkovom úložisku na disku (vyššie už bolo popísané, že skutočný zápis do stránkového úložiska sa vykonáva v procese, ktorý sa nazýva „checkpoint“ s určitým oneskorením jednotlivými vláknami).

Záznamy v WAL sa delia na logické a fyzické. Logické — to sú samotné kľúče a hodnoty. Fyzické — odrážajú zmeny stránok v stránkovom úložisku. Ak môžu byť logické záznamy užitočné aj pre iné prípady, fyzické záznamy sú potrebné iba na obnovenie v prípade pádu a potrebujú záznamy iba od posledného úspešného checkpointu. Tu sa nebudeme zaoberať podrobnosťami a vysvetľovať, prečo to funguje práve takto, ale kto má záujem, môže sa obrátiť na už spomínaný článok na Apache Ignite Wiki: Ignite Persistent Store — pod kapotou.

Na jeden logický záznam často pripadá niekoľko fyzických záznamov. To znamená, že napríklad jedna operácia put do cache ovplyvňuje niekoľko stránok v stránkovej pamäti (stránku so samotnými údajmi, stránky s indexmi, stránky s free-listami). Na niektorých syntetických testoch sa mi podarilo dosiahnuť, že fyzické záznamy zaberali až 90 % objemu WAL súboru. Pri tom ich potrebujete len veľmi krátky čas (podľa predvolieb je interval medzi checkpointami — 3 minúty). Logicky by bolo od týchto údajov po strate ich aktuálnosti sa zbaviť. Práve to vykonáva mechanizmus WAL compaction, zbavuje sa fyzických záznamov a komprimuje pomocou zip zostávajúce logické záznamy, pričom sa veľkosť súboru znižuje veľmi výrazne (niekedy aj desiatky krát).

Fyzický WAL sa skladá z niekoľkých segmentov (predvolene 10) pevných rozmerov (predvolene 64MB), ktoré sa prepisujú dookola. Akonáhle je aktuálny segment zaplnený, priradí sa mu nasledujúci segment, a zaplnený segment sa kopíruje do archívu pomocou samostatného vlákna. WAL kompresia už pracuje s archívnymi segmentami. Taktiež samostatné vlákno sleduje vykonávanie kontrolného bodu a začína sťahovanie po archívnych segmentoch, fyzické zápisy, ktoré už nie sú potrebné.

Data compression in Apache Ignite. Experience of Sber

Vplyv na výkon

Keďže WAL kompresia pracuje samostatným vláknom, nemala by mať priamy dopad na vykonávané operácie. Napriek tomu vytvára dodatočnú záťaž na CPU (kompresia) a disk (čítanie každého WAL segmentu z archívu a zapisovanie zkomprimovaných segmentov), takže ak je systém na hranici možností, tak povedie aj k degradácii výkonu.

Ako zapnúť a nastaviť

WAL kompresiu je možné povoliť pomocou vlastnosti WalCompactionEnabled v DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Taktiež, pomocou metódy DataStorageConfiguration.setWalCompactionLevel() je možné nastaviť úroveň kompresie, ak nie je spokojný s predvolenou hodnotou (BEST_SPEED).

Kompresia snímky WAL stránky

Ako to funguje

Už sme zistili, že záznamy WAL sa delia na logické a fyzické. Na každú zmenu každej stránky v stránkovej pamäti sa vytvára fyzický záznam WAL. Fyzické záznamy sa tiež delia na dva podtypy: záznam snímky stránky a delta záznam. Kedykoľvek zmeníme niečo na stránke a pretransformujeme ju z čistého stavu na špinavý, v WAL sa zachováva úplná kópia tejto stránky (záznam snímky stránky – snapshot stránky). Aj keď zmeníme iba jeden bajt, v WAL sa zachová záznam veľkosti len o niečo väčšej ako veľkosť stránky. Ak však meníme niečo na už špinavej stránke, v WAL sa vytvára delta záznam, ktorý odráža iba zmeny v porovnaní s predchádzajúcim stavom stránky, ale nie celú stránku. Keďže resetovanie stavu stránok z špinavého na čistý sa vykonáva počas procesu kontrolného bodu, takmer všetky fyzické záznamy na začiatku kontrolného bodu budú pozostávať iba zo snímok stránok (pretože všetky stránky sú na začiatku kontrolného bodu čisté). Následne, ako sa blížime k ďalšiemu kontrolnému bodu, podiel delta záznamov začína rásť a opäť sa resetuje na začiatku nasledujúceho kontrolného bodu. Merania na niektorých syntetických testoch ukázali, že podiel snímok stránok v celkovom objeme fyzických záznamov dosahuje až 90%.

Myšlienka kompresie snímok stránok WAL spočíva v tom, aby sa snímky stránok komprezovali pomocou už existujúceho nástroja na kompresiu stránok (pozri kompresiu stránok na disku). Pri tom sa záznamy WAL ukladajú sekvenčne v režime append-only a nie je potrebná väzba záznamov na hranice blokov súborového systému, a preto tu, na rozdiel od mechanizmu kompresie stránok na disku, nepotrebujeme sparse súbory. Tým pádom bude tento mechanizmus fungovať nielen na operačnom systéme Linux. Okrem toho nám už nezáleží na tom, akú vysokú kompresiu sa nám podarilo dosiahnuť. Aj keď sme uvoľnili iba 1 bajt, je to už pozitívny výsledok a môžeme ukladať do WAL komprimované údaje, na rozdiel od kompresie stránok na disku, kde ukládame komprimovanú stránku iba ak sme uvoľnili viac než 1 blok súborového systému.

Stránky sú dobre komprimovateľné údaje, ich podiel na celkovom objeme WAL je veľmi vysoký, takže bez zmeny formátu súboru WAL môžeme dosiahnuť významné zníženie jeho veľkosti. Kompresia vrátane logických záznamov by si vyžadovala zmenu formátu a stratu kompatibility, napríklad pre vonkajších spotrebiteľov, ktorí môžu mať záujem o logické záznamy, pritom by to neprinieslo významné zmenšenie objemu súboru.

Rovnako ako pri kompresii diskových stránok, pre kompresiu snímok stránok WAL môžu byť použité algoritmy kompresie ZSTD, LZ4, Snappy, ako aj režim SKIP_GARBAGE.

Vplyv na výkon

Nie je ťažké si všimnúť, že priame zapnutie kompresie snímok stránok WAL ovplyvňuje iba prúdy, ktoré ukladajú dáta do stránkovej pamäte, teda tie prúdy, ktoré menia dáta v cache. Čítanie z fyzických záznamov WAL sa deje iba jednorazovo, v momente obnovy uzla po zlyhaní (a to iba v prípade zlyhania počas checkpointu).

Na prúdy, ktoré menia dáta, to vplýva nasledujúcim spôsobom: získavame negatívny efekt (CPU) z dôvodu nutnosti zakaždým komprimovať stránku pred zápisom na disk a pozitívny efekt (disk IO) z dôvodu zníženia množstva zapisovaných údajov. Zodpovedajúcim spôsobom, ak sa výkon systému obmedzuje na CPU, získavame malé zhoršenie, ak na diskový vstup/výstup — získavame nárast.

Nepriamo zníženie veľkosti WAL taktiež pozitívne ovplyvňuje prúdy, ktoré archivujú segmenty WAL, a prúdy WAL compaction.

Skutočné testy výkonu v našom prostredí na syntetických dátach ukázali mierny nárast (priepustnosť vzrástla o 10%-15%, latencia sa znížila o 10%-15%).

Ako zapnúť a nastaviť

Minimálna verzia Apache Ignite: 2.8. Zapnutie a nastavenie sa vykonáva nasledovne:

  • V class-path by mal byť modul ignite-compression. Predvolene sa nachádza v distribúcii Apache Ignite v adresári libs/optional a nie je zahrnutý v class-path. Jednoducho môžete presunúť adresár o jeden level vyššie do libs a pri spustení cez ignite.sh bude automaticky zahrnutý.
  • Trvalosť musí byť zapnutá (zapína sa cez DataRegionConfiguration.setPersistenceEnabled(true)).
  • Musí byť zadaný režim kompresie pomocou metódy DataStorageConfiguration.setWalPageCompression(), predvolene je kompresia vypnutá (režim DISABLED).
  • Voliteľne je možné zadať stupeň kompresie pomocou metódy DataStorageConfiguration.setWalPageCompression(), povolené hodnoty pre každý z režimov nájdete v javadoc k metóde.

Záver

Mechanizmy kompresie údajov v Apache Ignite môžu byť používané nezávisle jeden od druhého, ale rovnako sú prípustné aj akékoľvek ich kombinácie. Pochopenie princípov ich fungovania umožní určiť, ako dobre vyhovujú vašim úlohám vo vašom prostredí a s čím sa budete musieť pri ich používaní zmieriť. Kompresia diskových strán je určená na kompresiu hlavného úložiska a môže dosiahnuť priemerný stupeň kompresie. Kompresia snímok stránky WAL poskytne priemerný stupeň kompresie už pre súbory WAL, pričom pravdepodobne dokonca zvýši výkon. Kompresia WAL nebude mať pozitívny vplyv na výkon, ale maximálne zníži veľkosť súborov WAL odstránením fyzických záznamov.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster