Komprese dat v Apache Ignite. Sberova zkušenost

Komprese dat v Apache Ignite. Sberova zkušenostPři práci s velkými objemy dat může občas nastat problém s nedostatkem místa na disku. Jedním ze způsobů, jak tento problém vyřešit, je komprese, díky které si na stejném zařízení můžete dovolit zvětšit objemy úložiště. V tomto článku se podíváme na to, jak funguje komprese dat v Apache Ignite. Tento článek popisuje pouze metody komprese disku implementované v produktu. Jiné metody komprese dat (přes síť, v paměti), ať už implementované nebo ne, zůstanou mimo rozsah.

Takže když je povolen režim persistence, v důsledku změn v datech v mezipaměti začne Ignite zapisovat na disk:

  1. Obsah keší
  2. Write Ahead Log (dále jen WAL)

Již nějakou dobu existuje mechanismus pro kompresi WAL, nazývaný komprimace WAL. Nedávno vydaný Apache Ignite 2.8 představil další dva mechanismy, které umožňují komprimovat data na disku: kompresi stránky disku pro kompresi obsahu mezipaměti a kompresi snímku stránky WAL pro kompresi některých položek WAL. Další podrobnosti o všech třech těchto mechanismech níže.

Komprese stránky disku

Jak to funguje

Nejprve se velmi krátce podíváme na to, jak Ignite ukládá data. K ukládání se používá stránková paměť. Velikost stránky je nastavena na začátku uzlu a nelze ji v pozdějších fázích změnit; velikost stránky musí být také mocninou dvou a násobkem velikosti bloku souborového systému. Stránky se načítají do RAM z disku podle potřeby, velikost dat na disku může přesáhnout množství přidělené RAM. Pokud v paměti RAM není dostatek místa pro načtení stránky z disku, staré, již nepoužívané stránky budou z paměti RAM vyřazeny.

Data jsou uložena na disku v následující podobě: pro každý oddíl každé skupiny mezipaměti je vytvořen samostatný soubor; v tomto souboru se stránky objevují jedna za druhou ve vzestupném indexovém pořadí. Úplný identifikátor stránky obsahuje identifikátor skupiny mezipaměti, číslo oddílu a index stránky v souboru. Pomocí úplného identifikátoru stránky tedy můžeme jednoznačně určit soubor a posun v souboru pro každou stránku. Více o stránkovací paměti si můžete přečíst v článku Apache Ignite Wiki: Ignite Persistent Store – pod kapotou.

Mechanismus komprese stránky disku, jak už z názvu můžete uhodnout, funguje na úrovni stránky. Když je tento mechanismus povolen, data v paměti RAM se zpracovávají tak, jak jsou, bez jakékoli komprese, ale když jsou stránky uloženy z paměti RAM na disk, jsou komprimovány.

Ale komprimace každé stránky jednotlivě není řešením problému, musíte nějak zmenšit velikost výsledných datových souborů. Pokud již není velikost stránky pevná, nemůžeme již zapisovat stránky do souboru jednu po druhé, protože to může způsobit řadu problémů:

  • Pomocí indexu stránky nebudeme schopni vypočítat posun, o který se v souboru nachází.
  • Není jasné, co dělat se stránkami, které nejsou na konci souboru a měnit jejich velikost. Pokud se velikost stránky zmenší, místo, které uvolnila, zmizí. Pokud se velikost stránky zvětší, musíte pro ni hledat nové místo v souboru.
  • Pokud se stránka posune o počet bajtů, který není násobkem velikosti bloku souborového systému, pak její čtení nebo zápis bude vyžadovat dotyk o jeden další blok souborového systému, což může vést ke snížení výkonu.

Aby se předešlo řešení těchto problémů na vlastní úrovni, používá komprese stránky disku v Apache Ignite mechanismus souborového systému nazývaný řídké soubory. Řídký soubor je takový, ve kterém lze některé oblasti s nulovou výplní označit jako „díry“. V tomto případě nebudou pro ukládání těchto děr přiděleny žádné bloky souborového systému, což vede k úsporám místa na disku.

Je logické, že pro uvolnění bloku systému souborů musí být velikost díry větší nebo rovna bloku systému souborů, což ukládá další omezení velikosti stránky a Apache Ignite: aby měla komprese nějaký účinek, velikost stránky musí být přísně větší než velikost bloku systému souborů. Pokud je velikost stránky rovna velikosti bloku, pak nikdy nebudeme moci uvolnit jediný blok, protože pro uvolnění jednoho bloku musí komprimovaná stránka zabírat 0 bajtů. Pokud je velikost stránky rovna velikosti 2 nebo 4 bloků, budeme již moci uvolnit alespoň jeden blok, pokud je naše stránka komprimována alespoň na 50 %, respektive 75 %.

Takže konečný popis fungování mechanismu: Při zápisu stránky na disk je proveden pokus o komprimaci stránky. Pokud velikost komprimované stránky umožňuje uvolnit jeden nebo více bloků souborového systému, pak se stránka zapíše v komprimované podobě a místo uvolněných bloků se vytvoří „díra“ (provede se systémové volání fallocate() s praporkem děrování). Pokud velikost komprimované stránky neumožňuje uvolnění bloků, stránka se uloží tak, jak je, nekomprimovaná. Odsazení všech stránek se počítá stejným způsobem jako bez komprese, vynásobením indexu stránky velikostí stránky. Není vyžadováno vlastní přemisťování stránek. Posuny stránek, stejně jako bez komprese, spadají na hranice bloků souborového systému.

Komprese dat v Apache Ignite. Sberova zkušenost

V aktuální implementaci může Ignite pracovat pouze s řídkými soubory pod OS Linux; kompresi stránky na disku lze proto povolit pouze při použití Ignite na tomto operačním systému.

Kompresní algoritmy, které lze použít pro kompresi stránky disku: ZSTD, LZ4, Snappy. Kromě toho existuje provozní režim (SKIP_GARBAGE), ve kterém je vyhozen pouze nevyužitý prostor na stránce, aniž by byla aplikována komprese na zbývající data, což snižuje zatížení CPU ve srovnání s dříve uvedenými algoritmy.

Dopad na výkon

Bohužel jsem neprováděl skutečná měření výkonu na reálných stojanech, jelikož tento mechanismus neplánujeme použít ve výrobě, ale můžeme teoreticky spekulovat, kde prohrajeme a kde vyhrajeme.

K tomu si musíme pamatovat, jak se stránky čtou a zapisují při přístupu:

  • Při provádění operace čtení je nejprve prohledávána v RAM, pokud je hledání neúspěšné, je stránka načtena do RAM z disku stejným vláknem, které provádí čtení.
  • Při provádění operace zápisu je stránka v paměti RAM označena jako špinavá, ale stránka není okamžitě fyzicky uložena na disk vláknem provádějícím zápis. Všechny nečisté stránky se později v procesu kontrolního bodu uloží na disk v samostatných vláknech.

Takže dopad na operace čtení je:

  • Pozitivní (disk IO), kvůli snížení počtu čtených bloků souborového systému.
  • Negativní (CPU), kvůli dodatečné zátěži vyžadované operačním systémem pro práci s řídkými soubory. Je také možné, že se zde implicitně objeví další IO operace pro uložení složitější struktury řídkých souborů (bohužel nejsem obeznámen se všemi detaily, jak řídké soubory fungují).
  • Negativní (CPU), kvůli nutnosti dekomprimovat stránky.
  • Nemá žádný vliv na operace zápisu.
  • Vliv na proces kontrolního bodu (zde je vše podobné operacím čtení):
  • Pozitivní (disk IO), kvůli snížení počtu zapsaných bloků souborového systému.
  • Negativní (CPU, případně IO disku), kvůli práci s řídkými soubory.
  • Negativní (CPU), kvůli nutnosti komprese stránky.

Která strana vah nakloní váhu? To vše do značné míry závisí na prostředí, ale přikláním se k názoru, že komprese stránky na disku s největší pravděpodobností povede ke snížení výkonu na většině systémů. Navíc testy na jiných DBMS, které používají podobný přístup s řídkými soubory, ukazují pokles výkonu, když je povolena komprese.

Jak povolit a nakonfigurovat

Jak bylo uvedeno výše, minimální verze Apache Ignite, která podporuje kompresi stránky na disku, je 2.8 a podporován je pouze operační systém Linux. Povolte a nakonfigurujte následovně:

  • V cestě třídy musí být modul ignite-komprese. Ve výchozím nastavení se nachází v distribuci Apache Ignite v adresáři libs/optional a není součástí cesty ke třídě. Můžete jednoduše přesunout adresář o jednu úroveň výše do libs a poté, když jej spustíte přes ignite.sh, bude automaticky povolen.
  • Persistence musí být povolena (povoleno přes DataRegionConfiguration.setPersistenceEnabled(true)).
  • Velikost stránky musí být větší než velikost bloku souborového systému (můžete ji nastavit pomocí DataStorageConfiguration.setPageSize() ).
  • Pro každou mezipaměť, jejíž data je třeba komprimovat, musíte nakonfigurovat metodu komprese a (volitelně) úroveň komprese (metody CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

Zhutňování WAL

Jak to funguje

Co je WAL a proč je potřeba? Velmi stručně: toto je protokol, který obsahuje všechny události, které nakonec změní úložiště stránky. Je potřeba především k tomu, aby se v případě pádu dokázal zotavit. Jakákoli operace musí před předáním řízení uživateli nejprve zaznamenat událost do WAL, aby v případě selhání mohla být přehrána v protokolu a obnoveny všechny operace, na které uživatel obdržel úspěšnou odpověď, i když tyto operace nestihlo se projevit v úložišti stránky na disku (již výše Bylo popsáno, že vlastní zápis do úložiště stránek se provádí v procesu zvaném „checkpointing“ s určitým zpožděním samostatnými vlákny).

Záznamy ve WAL jsou rozděleny na logické a fyzické. Booleovské jsou klíče a hodnoty samotné. Fyzické – odráží změny stránek v úložišti stránek. Zatímco logické záznamy mohou být užitečné v některých jiných případech, fyzické záznamy jsou potřeba pouze pro obnovu v případě havárie a záznamy jsou potřeba pouze od posledního úspěšného kontrolního bodu. Zde se nebudeme rozepisovat a vysvětlovat, proč to takto funguje, ale zájemci mohou odkázat na již zmíněný článek na Apache Ignite Wiki: Ignite Persistent Store – pod kapotou.

Na jeden logický záznam často připadá několik fyzických záznamů. To znamená, že například jedna operace vložení do mezipaměti ovlivní několik stránek v paměti stránek (stránku se samotnými daty, stránky s indexy, stránky s volnými seznamy). V některých syntetických testech jsem zjistil, že fyzické záznamy zabírají až 90 % WAL souboru. Jsou však potřeba na velmi krátkou dobu (standardně je interval mezi kontrolními body 3 minuty). Bylo by logické se těchto dat po ztrátě relevance zbavit. Přesně to dělá mechanismus komprimace WAL: zbaví se fyzických záznamů a zkomprimuje zbývající logické záznamy pomocí zipu, přičemž se velikost souboru velmi výrazně (někdy až desítkykrát) zmenší.

Fyzicky se WAL skládá z několika segmentů (10 ve výchozím nastavení) s pevnou velikostí (ve výchozím nastavení 64 MB), které jsou cyklicky přepisovány. Jakmile je aktuální segment vyplněn, je další segment přiřazen jako aktuální a vyplněný segment je zkopírován do archivu pomocí samostatného vlákna. Zhutňování WAL již funguje s archivními segmenty. Jako samostatné vlákno také monitoruje provádění kontrolního bodu a zahajuje kompresi v segmentech archivu, pro které již nejsou potřeba fyzické záznamy.

Komprese dat v Apache Ignite. Sberova zkušenost

Dopad na výkon

Vzhledem k tomu, že komprimace WAL probíhá jako samostatné vlákno, neměl by mít žádný přímý dopad na prováděné operace. Stále však na pozadí zatěžuje CPU (komprese) a disk (čtení každého segmentu WAL z archivu a zápis komprimovaných segmentů), takže pokud systém běží na maximální kapacitu, povede to také ke snížení výkonu.

Jak povolit a nakonfigurovat

Pomocí vlastnosti můžete povolit zhutňování WAL WalCompactionEnabled в DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Také pomocí metody DataStorageConfiguration.setWalCompactionLevel() můžete nastavit úroveň komprese, pokud nejste spokojeni s výchozí hodnotou (BEST_SPEED).

Komprese snímku stránky WAL

Jak to funguje

Již jsme zjistili, že ve WAL se záznamy dělí na logické a fyzické. Pro každou změnu každé stránky se v paměti stránek vygeneruje fyzický záznam WAL. Fyzické záznamy se také dělí na 2 podtypy: záznam snímku stránky a záznam delta. Pokaždé, když na stránce něco změníme a převedeme ji z čistého stavu do nečistého stavu, úplná kopie této stránky se uloží do WAL (záznam snímku stránky). I kdybychom ve WAL změnili pouze jeden bajt, záznam bude o něco větší než velikost stránky. Pokud na již špinavé stránce něco změníme, vytvoří se ve WAL delta záznam, který odráží pouze změny oproti předchozímu stavu stránky, nikoli však celou stránku. Vzhledem k tomu, že resetování stavu stránek z nečistých na čisté se provádí během procesu kontrolního bodu, ihned po spuštění kontrolního bodu budou téměř všechny fyzické záznamy sestávat pouze ze snímků stránek (protože všechny stránky bezprostředně po spuštění kontrolního bodu jsou čisté) a když se přiblížíme k dalšímu kontrolnímu bodu, zlomek delta záznamu začne růst a znovu se resetuje na začátku dalšího kontrolního bodu. Měření v některých syntetických testech ukázala, že podíl snímků stránek na celkovém objemu fyzických záznamů dosahuje 90 %.

Myšlenka komprese snímku stránky WAL je komprimovat snímky stránky pomocí hotového nástroje pro kompresi stránky (viz komprese stránky disku). Zároveň se ve WAL záznamy ukládají sekvenčně v režimu pouze připojování a není potřeba vázat záznamy na hranice bloků souborového systému, takže zde na rozdíl od mechanismu komprese stránky disku nepotřebujeme řídké soubory na vše, takže tento mechanismus bude fungovat nejen na OS Linux. Navíc už nám nezáleží na tom, jak moc jsme stránku dokázali zkomprimovat. I když jsme uvolnili 1 bajt, je to již pozitivní výsledek a můžeme uložit komprimovaná data ve WAL, na rozdíl od komprese diskové stránky, kde komprimovanou stránku uložíme pouze v případě, že jsme uvolnili více než 1 blok souborového systému.

Stránky jsou vysoce komprimovatelná data, jejich podíl na celkovém objemu WAL je velmi vysoký, takže bez změny formátu souboru WAL můžeme dosáhnout výrazného zmenšení jeho velikosti. Komprese, včetně logických záznamů, by vyžadovala změnu formátu a ztrátu kompatibility například pro externí spotřebitele, kteří by mohli mít zájem o logické záznamy, ale nevedla by k výraznému zmenšení velikosti souboru.

Stejně jako u komprese stránky disku může komprese snímku stránky WAL používat kompresní algoritmy ZSTD, LZ4, Snappy a také režim SKIP_GARBAGE.

Dopad na výkon

Není těžké si všimnout, že přímé povolení komprese snímku stránky WAL ovlivňuje pouze vlákna, která zapisují data do paměti stránky, tedy vlákna, která mění data v mezipaměti. Čtení fyzických záznamů z WAL nastane pouze jednou, v okamžiku, kdy je uzel po pádu zvednut (a to pouze v případě, že spadne během kontrolního bodu).

To ovlivňuje vlákna, která mění data následujícím způsobem: máme negativní efekt (CPU) kvůli nutnosti komprimovat stránku pokaždé před zápisem na disk a pozitivní efekt (vstup disku) kvůli snížení množství zapsaná data. V souladu s tím je zde vše jednoduché: pokud je výkon systému omezen CPU, dostaneme mírnou degradaci, pokud je omezen diskovými I/O, dostaneme zvýšení.

Zmenšení velikosti WAL nepřímo také ovlivní (pozitivně) proudy, které ukládají segmenty WAL do archivu a proudy komprimace WAL.

Testy reálného výkonu v našem prostředí pomocí syntetických dat ukázaly mírný nárůst (propustnost vzrostla o 10 %-15 %, latence se snížila o 10 %-15 %).

Jak povolit a nakonfigurovat

Minimální verze Apache Ignite: 2.8. Povolte a nakonfigurujte následovně:

  • V cestě třídy musí být modul ignite-komprese. Ve výchozím nastavení se nachází v distribuci Apache Ignite v adresáři libs/optional a není součástí cesty ke třídě. Můžete jednoduše přesunout adresář o jednu úroveň výše do libs a poté, když jej spustíte přes ignite.sh, bude automaticky povolen.
  • Persistence musí být povolena (povoleno přes DataRegionConfiguration.setPersistenceEnabled(true)).
  • Režim komprese musí být nastaven pomocí metody DataStorageConfiguration.setWalPageCompression(), komprese je ve výchozím nastavení zakázána (režim DISABLED).
  • Volitelně můžete pomocí metody nastavit úroveň komprese DataStorageConfiguration.setWalPageCompression(), platné hodnoty pro každý režim najdete v javadocu.

Závěr

Uvažované mechanismy komprese dat v Apache Ignite lze používat nezávisle na sobě, ale přijatelná je také jakákoli jejich kombinace. Pochopení toho, jak fungují, vám umožní určit, jak jsou vhodné pro vaše úkoly ve vašem prostředí a co budete muset při jejich používání obětovat. Komprese stránky disku je navržena tak, aby komprimovala hlavní úložiště a může poskytnout střední kompresní poměr. Komprese snímku stránky WAL poskytne průměrný stupeň komprese pro soubory WAL a s největší pravděpodobností dokonce zlepší výkon. Zhutnění WAL nebude mít pozitivní vliv na výkon, ale co nejvíce zmenší velikost souborů WAL odstraněním fyzických záznamů.

Zdroj: www.habr.com

Přidat komentář