Kompresní data v Apache Ignite. Zkušenosti Sberbanky

Kompresní data v Apache Ignite. Zkušenosti SberbankyPři práci s velkým objemem dat se někdy může akutně vynořit problém nedostatku místa na discích. Jedním z řešení tohoto problému je komprese, díky které si na stejném zařízení můžete dovolit zvýšit objemy úložiště. V tomto článku se podíváme, jak funguje komprese dat v Apache Ignite. Článek se bude zabývat pouze metodami komprese implementovanými uvnitř produktu na disku. Ostatní metody komprese dat (přes síť, v paměti), ať už realizované, nebo ne, zůstanou mimo rozsah článku.

Takže při zapnutém režimu persistence, v důsledku změny dat v cache, Ignite začne zapisovat na disk:

  1. Obsah cache
  2. Žurnál pro zapisování předem (Write Ahead Log, dále jen WAL)

Pro kompresi WAL již existuje mechanismus, který se nazývá WAL compaction. V nedávno vydaném Apache Ignite 2.8 se objevily další dva mechanizmy, které umožňují komprimovat data na disku: disk page compression pro kompresi obsahu cache a WAL page snapshot compression pro kompresi některých záznamů WAL. Více o všech těchto třech mechanizmech níže.

Disk page compression

Jak to funguje

Nejprve se velmi stručně zamyslíme nad tím, jak Ignite ukládá data. Pro ukládání se používá stránková paměť. Velikost stránky je stanovena při spuštění uzlu a nemůže být změněna v pozdějších fázích, navíc musí být velikost stránky mocninou dvou a dělitelná velikostí bloku souborového systému. Stránky jsou načítány do RAM z disku podle potřeby, velikost dat na disku může překročit objem přidělené RAM. V případě nedostatku místa v RAM pro načtení stránky z disku budou staré, již nepoužívané stránky vytlačeny z RAM.

Na disku jsou data uchovávána následujícím způsobem: pro každou partici každé cache skupiny se vytváří samostatný soubor, v tomto souboru jdou stránky za sebou vzestupně dle indexu. Kompletní identifikátor stránky obsahuje identifikátor cache skupiny, číslo partition a index stránky v souboru. Tím pádem podle kompletního identifikátoru stránky můžeme jednoznačně určit soubor a offset v souboru pro každou stránku. Podrobněji o uspořádání stránkové paměti se můžete dočíst v článku na Apache Ignite Wiki: Ignite Persistent Store — pod kapotou.

Mechanismus komprese diskových stránek, jak lze odvodit z názvu, funguje na úrovni stránek. Po aktivaci tohoto mechanismu se práce s daty v RAM provádí tak, jak jsou, bez jakékoli komprese, ale v okamžiku ukládání stránek z RAM na disk se provádí jejich komprese.

Ale stlačit každou stránku zvlášť ještě není řešení problému, je třeba nějak snížit velikost výsledných souborů s daty. Pokud se velikost stránky přestane pevně definovat, už nemůžeme zapisovat stránky do souboru jednu po druhé, protože to může vyvolat celou řadu problémů:

  • Nebudeme schopni pomocí indexu stránky vypočítat offset, na kterém se nachází v souboru.
  • Není jasné, co dělat se stránkami, které se nenacházejí na konci souboru a mění svou velikost. Pokud se velikost stránky zmenšuje, místo, které uvolnila, se ztrácí. Pokud se velikost stránky zvětšuje, pro ni je třeba hledat už nové místo v souboru.
  • Pokud se stránka posune o počet bajtů, který není násobkem velikosti bloku souborového systému, bude pro její čtení nebo zápis nutné zasáhnout o jeden blok souborového systému více, což může vést k degradaci výkonu.

Aby se tyto problémy neřešily na své úrovni, uvádí komprese diskových stránek v Apache Ignite mechanismus souborového systému nazvaný sparse files. Sparse (řídce osídlený) soubor je takový soubor, ve kterém mohou být některé oblasti vyplněné nulami označeny jako „díry“. Při tom bloky souborového systému pro ukládání těchto děr nebudou přiděleny, čímž se dosahuje úspory místa na disku.

Je logické, že aby bylo možné uvolnit blok souborového systému, musí být velikost díry větší nebo rovna velikosti bloku souborového systému, což klade další omezení na velikost stránky v Apache Ignite: aby komprese měla nějaký efekt, musí být velikost stránky striktně větší než velikost bloku souborového systému. Pokud bude velikost stránky rovna velikosti bloku, nikdy nebudeme schopni uvolnit žádný blok, protože aby bylo možné uvolnit jediný blok, musí stlačená stránka zabírat 0 bajtů. Pokud bude však velikost stránky rovna velikosti dvou nebo čtyř bloků, budeme schopni uvolnit alespoň jeden blok, pokud se naše stránka stlačí alespoň na 50 % nebo na 75 % příslušně.

Takže shrnutí fungování mechanismu: Při zápisu stránky na disk se pokoušíme stránku komprimovat. Pokud velikost komprimované stránky umožňuje uvolnit jeden nebo více bloků souborového systému, stránka se zapíše v komprimované podobě, na místě uvolněných bloků se „vyvrtá díra“ (provádí se systémový výpis s příznakem „punch hole“). fallocate() Pokud velikost komprimované stránky neumožňuje uvolnit bloky, stránka se ukládá tak, jak je, v nezkomprimované podobě. Všechny ofsety stránek se počítají stejně jako bez komprese, násobením indexu stránky velikostí stránky. Žádná relokace stránek není nutná. Ofsety stránek, stejně jako bez komprese, spadají na hranice bloků souborového systému.

Kompresní data v Apache Ignite. Zkušenosti Sberbanky

V aktuální implementaci Ignite umí pracovat se sparse soubory pouze pod OS Linux, a proto může být disková komprese stránek povolena pouze při používání Ignite na tomto operačním systému.

Algoritmy komprese, které mohou být použity pro diskovou kompresi stránek: ZSTD, LZ4, Snappy. Kromě toho existuje pracovní režim (SKIP_GARBAGE), při kterém se pouze zahazuje nepoužívané místo na stránce bez použití komprese na zbývajících datech, což umožňuje snížit zátěž CPU ve srovnání s dříve zmíněnými algoritmy.

Vliv na výkonnost

Bohužel jsem neprováděl skutečné měření výkonnosti na reálných strojích, protože neplánujeme tento mechanismus použít v produkci, ale můžeme teoreticky uvažovat, kde bychom mohli ztratit, a kde získat.

K tomu si musíme připomenout, jak probíhá čtení a zápis stránek při přístupu k nim:

  • Při vykonávání operace čtení se nejprve provede její vyhledání v RAM, pokud vyhledávání selže, stránka se načte do RAM z disku stejným vláknem, které provádí čtení.
  • Při vykonávání operace zápisu je stránka v RAM označena jako špinavá, přičemž fyzické uložení stránky na disk se okamžitě ve vlákně provádějícím zápis neprovádí. Všechny špinavé stránky se ukládají na disk později v procesu checkpointu jednotlivými vlákny.

Takže vliv na operace čtení:

  • Pozitivní (disk IO), díky snížení počtu přečtených bloků souborového systému.
  • Negativní (CPU) z důvodu další zátěže, kterou operační systém potřebuje pro práci s sparse soubory. Také zde mohou implicitně vzniknout další IO operace pro uchování složitější struktury sparse souboru (s veškerými detaily o fungování sparse souborů, bohužel, nejsem obeznámen).
  • Negativní (CPU) kvůli nutnosti dekomprese stránek.
  • Žádný vliv na operace zápisu.
  • Vliv na proces kontrolního bodu (zde je vše podobné operacím čtení):
  • Pozitivní (disk IO) díky snížení počtu zapsaných bloků souborového systému.
  • Negativní (CPU, možná disk IO) z důvodu práce se sparse soubory.
  • Negativní (CPU) kvůli potřebě komprese stránek.

Která strana vah převaží? To velmi závisí na prostředí, ale jsem nakloněn k tomu, že komprese diskových stránek povede spíše k degradaci výkonu na většině systémů. O to víc, že testy na jiných DBMS, které používají podobný přístup se sparse soubory, ukazují pokles výkonu při zapnuté kompresi.

Jak aktivovat a nastavit

Jak již bylo uvedeno výše, minimální verze Apache Ignite, která podporuje kompresi diskových stránek: 2.8 a je podporována pouze operačním systémem Linux. Aktivace a nastavení se provádí následujícím způsobem:

  • V class-path musí být modul ignite-compression. Ve výchozím nastavení se nachází v distribuci Apache Ignite v adresáři libs/optional a není zahrnut do class-path. Můžete jednoduše přesunout adresář o jeden úroveň výš do libs, a pak při spuštění skrze ignite.sh bude automaticky zahrnut.
  • Perzistence musí být povolena (Povoluje se skrze 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ždý cache, jehož data je třeba komprimovat, je nutné v konfiguraci nastavit metodu komprese a (volitelně) úroveň komprese (metody CacheConfiguration.setDiskPageCompression(), CacheConfiguration.setDiskPageCompressionLevel()).

WAL komprese

Jak to funguje

Co je to WAL a k čemu je potřeba? Velmi stručně: je to žurnál, do kterého se zaznamenávají všechny události měnící na konci stránkové úložiště. Je zapotřebí především pro možnost obnovení v případě selhání. Jakákoli operace musí před předáním kontroly uživateli nejprve zapsat událost do WAL, aby v případě pádu bylo možné znovu přehrát žurnál a obnovit všechny operace, za které uživatel obdržel úspěšnou odpověď, i když tyto operace ještě nebyly odraženy ve stránkovém úložišti na disku (dříve bylo uvedeno, že skutečné zápisy do stránkového úložiště se provádějí v procesu nazvaném „checkpoint“ se zpožděním oddělenými vlákny).

Záznamy v WAL se dělí na logické a fyzické. Logické záznamy představují samotné klíče a hodnoty. Fyzické záznamy odrážejí změny stránek ve stránkovém úložišti. Zatímco logické záznamy mohou být užitečné pro různé případy, fyzické záznamy jsou zapotřebí pouze pro obnovení v případě selhání a potřebujeme záznamy pouze od posledního úspěšného checkpointu. Nebudeme se zde zabývat podrobnostmi a vysvětlovat, proč to tak funguje, ale kdo má zájem, může se obrátit 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 put do cache ovlivňuje několik stránek ve stránkové paměti (stránku s daty, stránky s indexy, stránky s free-listy). Na některých syntetických testech jsem zjistil, že fyzické záznamy zabíraly až 90% objemu souboru WAL. Tyto záznamy potřebujeme jen po velmi krátkou dobu (podle výchozího nastavení je interval mezi checkpointy 3 minuty). Bylo by logické se těchto dat zbavit, jakmile ztratí svou aktuálnost. To je to, co provádí mechanismus WAL compaction, zbavuje se fyzických záznamů a komprimuje zbývající logické záznamy pomocí zip, přičemž velikost souboru se velmi výrazně zmenšuje (někdy až desítkykrát).

Fyzický WAL se skládá z několika segmentů (výchozí počet 10), které mají pevnou velikost (výchozí velikost 64 MB) a jsou přepisovány cyklicky. Jakmile je aktuální segment zaplněn, je mu přidělen další následující segment a zaplněný segment je kopírován do archivu pomocí samostatného vlákna. WAL komprese již funguje s archivními segmenty. Také pomocí samostatného vlákna sleduje provádění kontrolního bodu a zahajuje kompresi u archivních segmentů, jejichž fyzické záznamy již nejsou potřeba.

Kompresní data v Apache Ignite. Zkušenosti Sberbanky

Vliv na výkonnost

Protože WAL komprese pracuje ve svém vlastním vlákně, nemělo by to mít přímý vliv na vykonávané operace. Přesto však představuje dodatečné zatížení pro CPU (komprese) a disk (čtení každého WAL segmentu z archivu a zápis komprimovaných segmentů), takže pokud systém pracuje na hraně svých možností, může také vést k degradaci výkonu.

Jak aktivovat a nastavit

WAL kompresi lze aktivovat pomocí vlastnosti WalCompactionEnabled v DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Také pomocí metody DataStorageConfiguration.setWalCompactionLevel() lze nastavit úroveň komprese, pokud vám nevyhovuje výchozí hodnota (BEST_SPEED).

Kompresní snapshot WAL stránkování

Jak to funguje

Dříve jsme již zjistili, že záznamy WAL se dělí na logické a fyzické. Na každou změnu každé stránky v paměti stránky se vytváří fyzický záznam WAL. Fyzičtí záznamy se zase dělí na 2 podtypy: záznam snímku stránky a záznam rozdílu. Když něco změníme na stránce a převedeme ji ze stavu nečistoty do stavu čistoty, v WAL se uchovává kompletní kopie této stránky (záznam snímku stránky — snapshot stránky). I když jsme změnili pouze jeden byte, v WAL se zachová záznam o něco větší než velikost stránky. Pokud však něco změníme na již špinavé stránce, v WAL se vytvoří záznam rozdílu, který odráží pouze změny ve srovnání s předchozím stavem stránky, nikoli celou stránku jako celek. Vzhledem k tomu, že resetování stavu stránek z špinavého na čistý probíhá během procesu kontrolního bodu, téměř všechny fyzické záznamy budou po začátku kontrolního bodu sestávat pouze ze snímků stránek (protože všechny stránky po začátku kontrolního bodu jsou čisté). Pak, jak se blížíme k dalšímu kontrolnímu bodu, podíl záznamů rozdílu začíná růst a znovu se resetuje na začátku dalšího kontrolního bodu. Měření na některých syntetických testech ukázala, že podíl snímků stránek v celkovém objemu fyzických záznamů dosahuje 90%.

Myšlenka komprese snímku stránky WAL spočívá v tom, že komprimuje snímky stránek pomocí již existujícího nástroje pro kompresi stránek (viz. komprese diskových stránek). Záznamy v WAL přitom jsou uchovávány sekvenčně v režimu pouze pro přidání a není potřeba provazování záznamů na hranicích bloků souborového systému, proto zde, na rozdíl od mechanismu komprese diskových stránek, nepotřebujeme sparse soubory, a tedy tento mechanismus bude fungovat nejen na operačním systému Linux. Navíc už není důležité, jak moc jsme byli schopni stránku komprimovat. I když jsme uvolnili 1 byte, to je již pozitivní výsledek a můžeme uchovávat v WAL komprimovaná data, na rozdíl od komprese diskových stránek, kde uchováváme komprimovanou stránku pouze pokud jsme uvolnili více než 1 blok souborového systému.

Stránky jsou dobře komprimovatelné data, jejich podíl na celkovém objemu WAL je velmi vysoký, a tudíž můžeme výrazně zkrátit jejich velikost, aniž bychom změnili formát WAL souboru. Komprese logických záznamů by si vyžádala změnu formátu a ztrátu kompatibility například pro externí odběratele, kterým by mohly být zajímavé logické záznamy, přičemž by to nepřineslo významné snížení objemu souboru.

Pro kompresi snímků WAL stránek mohou být použity kompresní algoritmy ZSTD, LZ4, Snappy a také režim SKIP_GARBAGE, stejně jako u komprese stránkových disků.

Vliv na výkonnost

Jak není těžké si všimnout, přímé zapnutí komprese snímků WAL stránek ovlivňuje pouze vlákna, která zapisují data do stránkového paměti, to znamená, že ovlivňuje těch, kteří mění data v cache. Čtení fyzických záznamů z WAL probíhá pouze jednorázově, v okamžiku spuštění uzlu po pádu (a pouze v případě pádu během checkpointingu).

Na vlákna měnící data to má následující dopad: získáváme negativní efekt (CPU) kvůli nutnosti každé stránce komprimovat před zápisem na disk a pozitivní efekt (disk IO) díky snížení množství zapisovaných dat. Odpovídajícím způsobem, je to jednoduché, pokud výkon systému naráží na CPU, dojde k mírnému poklesu, pokud na diskový I/O — dojde k nárůstu.

Nepřímo snížení velikosti WAL také pozitivně ovlivňuje vlákna, která archivují segmenty WAL a na vlákna WAL komprese.

Skutečné výkonnostní testy v našem prostředí na syntetických datech ukázaly mírný nárůst (průchodnost vzrostla o 10-15 %, latence se snížila o 10-15 %).

Jak aktivovat a nastavit

Minimální verze Apache Ignite: 2.8. Aktivace a nastavení se provádí následujícím způsobem:

  • V class-path musí být modul ignite-compression. Ve výchozím nastavení se nachází v distribuci Apache Ignite v adresáři libs/optional a není zahrnut do class-path. Můžete jednoduše přesunout adresář o jeden úroveň výš do libs, a pak při spuštění skrze ignite.sh bude automaticky zahrnut.
  • Perzistence musí být povolena (Povoluje se skrze DataRegionConfiguration.setPersistenceEnabled(true)).
  • Musí být nastaven režim komprese pomocí metody DataStorageConfiguration.setWalPageCompression(), ve výchozím nastavení je komprese vypnuta (režim DISABLED).
  • Volitelně lze nastavit úroveň komprese pomocí metody DataStorageConfiguration.setWalPageCompression(), povolené hodnoty pro každý z režimů naleznete v javadoc k metodě.

Závěr

Zvážené mechanismy komprese dat v Apache Ignite mohou být používány nezávisle na sobě, ale také jsou povoleny jakékoli jejich kombinace. Pochopení principů jejich fungování umožní zjistit, jak dobře vyhovují vašim úkolům ve vašem prostředí a co budete muset obětovat při jejich použití. Komprese diskových stránek je určena k tomu, aby zkomprimovala hlavní úložiště a může poskytnout průměrný stupeň komprese. Komprese snapshotu stránek WAL již poskytne střední stupeň komprese souborů WAL, přičemž pravděpodobně dokonce zlepší výkon. Komprese WAL nemá pozitivní vliv na výkon, ale maximálně zkrátí velikost souborů WAL odstraněním fyzických záznamů.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster