Stiskanje podatkov v Apache Ignite. Sberjeva izkušnja

Stiskanje podatkov v Apache Ignite. Sberjeva izkušnjaPri delu z velikimi količinami podatkov se lahko včasih pojavi problem pomanjkanja prostora na disku. Eden od načinov za rešitev te težave je stiskanje, zahvaljujoč kateremu si lahko na isti opremi privoščite povečanje količine pomnilnika. V tem članku si bomo ogledali, kako deluje stiskanje podatkov v Apache Ignite. V tem članku bodo opisane samo metode stiskanja diska, ki so implementirane v izdelku. Druge metode stiskanja podatkov (preko omrežja, v pomnilniku), ne glede na to, ali so implementirane ali ne, bodo ostale izven obsega.

Torej, ko je omogočen način obstojnosti, začne Ignite zaradi sprememb podatkov v predpomnilnikih pisati na disk:

  1. Vsebina predpomnilnikov
  2. Dnevnik pisanja naprej (v nadaljevanju preprosto WAL)

Že nekaj časa obstaja mehanizem za stiskanje WAL, ki se imenuje stiskanje WAL. Nedavno izdan Apache Ignite 2.8 je predstavil še dva mehanizma, ki omogočata stiskanje podatkov na disku: stiskanje strani diska za stiskanje vsebine predpomnilnikov in stiskanje posnetkov strani WAL za stiskanje nekaterih vnosov WAL. Več podrobnosti o vseh treh teh mehanizmih spodaj.

Stiskanje strani diska

Kako to deluje

Najprej si na kratko oglejmo, kako Ignite shranjuje podatke. Pomnilnik strani se uporablja za shranjevanje. Velikost strani je nastavljena na začetku vozlišča in je ni mogoče spremeniti v poznejših fazah; prav tako mora biti velikost strani potenca dvojke in večkratnik velikosti bloka datotečnega sistema. Strani se po potrebi naložijo v RAM z diska; velikost podatkov na disku lahko preseže količino dodeljenega RAM-a. Če v RAM-u ni dovolj prostora za nalaganje strani z diska, bodo stare, neuporabljene strani izločene iz RAM-a.

Podatki so shranjeni na disku v naslednji obliki: za vsako particijo vsake predpomnilniške skupine se ustvari ločena datoteka; v tej datoteki se strani pojavljajo ena za drugo v naraščajočem vrstnem redu indeksa. Identifikator celotne strani vsebuje identifikator skupine predpomnilnika, številko particije in indeks strani v datoteki. Tako lahko z uporabo identifikatorja celotne strani enolično določimo datoteko in odmik v datoteki za vsako stran. Več o stranskem pomnilniku lahko preberete v članku Apache Ignite Wiki: Ignite Persistent Store - pod pokrovom.

Mehanizem stiskanja strani diska, kot lahko uganete iz imena, deluje na ravni strani. Ko je ta mehanizem omogočen, se podatki v RAM-u obdelujejo takšni, kot so, brez stiskanja, ko pa so strani shranjene iz RAM-a na disk, so stisnjene.

Toda stiskanje vsake strani posebej ni rešitev težave; morate nekako zmanjšati velikost nastalih podatkovnih datotek. Če velikost strani ni več fiksna, ne moremo več pisati strani v datoteko eno za drugo, saj lahko to povzroči številne težave:

  • Z uporabo indeksa strani ne bomo mogli izračunati odmika, po katerem se nahaja v datoteki.
  • Ni jasno, kaj storiti s stranmi, ki niso na koncu datoteke in spreminjajo svojo velikost. Če se velikost strani zmanjša, prostor, ki ga je sprostila, izgine. Če se velikost strani poveča, morate zanjo poiskati novo mesto v datoteki.
  • Če se stran premakne za število bajtov, ki ni večkratnik velikosti bloka datotečnega sistema, se bo za njeno branje ali pisanje treba dotakniti še enega bloka datotečnega sistema, kar lahko povzroči poslabšanje zmogljivosti.

Da bi se izognili reševanju teh težav na lastni ravni, stiskanje strani diska v Apache Ignite uporablja mehanizem datotečnega sistema, imenovan redke datoteke. Redka datoteka je tista, v kateri so nekatera področja z ničlo lahko označena kot "luknje". V tem primeru za shranjevanje teh lukenj ne bodo dodeljeni bloki datotečnega sistema, kar bo prihranilo prostor na disku.

Logično je, da mora biti za sprostitev bloka datotečnega sistema velikost luknje večja ali enaka bloku datotečnega sistema, kar nalaga dodatno omejitev velikosti strani in Apache Ignite: da bi stiskanje imelo kakršen koli učinek, velikost strani mora biti strogo večja od velikosti bloka datotečnega sistema. Če je velikost strani enaka velikosti bloka, potem nikoli ne bomo mogli sprostiti enega bloka, saj mora za sprostitev enega bloka stisnjena stran zavzemati 0 bajtov. Če je velikost strani enaka velikosti 2 ali 4 blokov, bomo že lahko sprostili vsaj en blok, če bo naša stran stisnjena na vsaj 50% oziroma 75%.

Tako je končni opis delovanja mehanizma: Pri zapisovanju strani na disk se stran poskuša stisniti. Če velikost stisnjene strani omogoča sprostitev enega ali več blokov datotečnega sistema, je stran zapisana v stisnjeni obliki in na mestu sproščenih blokov se naredi "luknja" (izvede se sistemski klic fallocate() z zastavico za luknjanje). Če velikost stisnjene strani ne dovoljuje sprostitve blokov, se stran shrani kot je, nestisnjena. Vsi odmiki strani se izračunajo na enak način kot brez stiskanja, tako da se indeks strani pomnoži z velikostjo strani. Samostojno prestavljanje strani ni potrebno. Odmiki strani, tako kot brez stiskanja, padejo na meje blokov datotečnega sistema.

Stiskanje podatkov v Apache Ignite. Sberjeva izkušnja

V trenutni implementaciji lahko Ignite deluje le z redkimi datotekami pod OS Linux; skladno s tem je stiskanje strani diska mogoče omogočiti le, če uporabljate Ignite v tem operacijskem sistemu.

Algoritmi stiskanja, ki se lahko uporabljajo za stiskanje strani diska: ZSTD, LZ4, Snappy. Poleg tega obstaja način delovanja (SKIP_GARBAGE), v katerem se izloči samo neuporabljen prostor na strani brez kompresije preostalih podatkov, kar zmanjša obremenitev CPU v primerjavi s predhodno naštetimi algoritmi.

Vpliv na uspešnost

Dejanskih meritev zmogljivosti na realnih stojalih žal nisem izvajal, saj tega mehanizma ne nameravamo uporabljati v proizvodnji, lahko pa teoretično špekuliramo, kje bomo izgubili in kje zmagali.

Da bi to naredili, si moramo zapomniti, kako se strani berejo in pišejo, ko do njih dostopamo:

  • Pri operaciji branja se najprej išče v RAM-u, če je iskanje neuspešno, stran naloži v RAM z diska ista nit, ki izvaja branje.
  • Ko se izvede operacija pisanja, je stran v RAM-u označena kot umazana, vendar nit, ki izvaja pisanje, strani ne shrani takoj fizično na disk. Vse umazane strani se pozneje v procesu kontrolne točke shranijo na disk v ločenih nitih.

Vpliv na operacije branja je torej:

  • Pozitivno (disk IO), zaradi zmanjšanja števila prebranih blokov datotečnega sistema.
  • Negativno (CPU), zaradi dodatne obremenitve, ki jo zahteva operacijski sistem za delo z redkimi datotekami. Možno je tudi, da se tukaj implicitno prikažejo dodatne operacije IO, da se shrani bolj zapletena struktura redkih datotek (žal nisem seznanjen z vsemi podrobnostmi o delovanju redkih datotek).
  • Negativno (CPE), zaradi potrebe po dekompresiji strani.
  • Ni vpliva na pisalne operacije.
  • Vpliv na postopek kontrolne točke (tukaj je vse podobno operacijam branja):
  • Pozitivno (disk IO), zaradi zmanjšanja števila zapisanih blokov datotečnega sistema.
  • Negativno (CPE, morda disk IO), zaradi dela z redkimi datotekami.
  • Negativno (CPE), zaradi potrebe po stiskanju strani.

Katera stran tehtnice bo prevesila tehtnico? Vse je zelo odvisno od okolja, vendar sem nagnjen k prepričanju, da bo stiskanje strani diska najverjetneje povzročilo poslabšanje zmogljivosti večine sistemov. Poleg tega testi na drugih DBMS, ki uporabljajo podoben pristop z redkimi datotekami, kažejo padec zmogljivosti, ko je omogočeno stiskanje.

Kako omogočiti in konfigurirati

Kot je navedeno zgoraj, je najmanjša različica Apache Ignite, ki podpira stiskanje diskovnih strani, 2.8 in je podprt samo operacijski sistem Linux. Omogočite in konfigurirajte na naslednji način:

  • V poti razreda mora obstajati modul ignite-compression. Privzeto se nahaja v distribuciji Apache Ignite v imeniku libs/optional in ni vključen v pot do razreda. Imenik lahko preprosto premaknete eno raven višje v libs in potem, ko ga zaženete prek ignite.sh, bo samodejno omogočen.
  • Vztrajnost mora biti omogočena (omogočeno prek DataRegionConfiguration.setPersistenceEnabled(true)).
  • Velikost strani mora biti večja od velikosti bloka datotečnega sistema (nastavite jo lahko z DataStorageConfiguration.setPageSize() ).
  • Za vsak predpomnilnik, katerega podatke je treba stisniti, morate konfigurirati način stiskanja in (izbirno) stopnjo stiskanja (metode CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

Zbijanje WAL

Kako to deluje

Kaj je WAL in zakaj je potreben? Zelo na kratko: to je dnevnik, ki vsebuje vse dogodke, ki na koncu spremenijo shranjevanje strani. Potreben je predvsem za okrevanje v primeru padca. Vsaka operacija, preden prepusti nadzor uporabniku, mora najprej zabeležiti dogodek v WAL, tako da se lahko v primeru napake predvaja v dnevniku in obnovi vse operacije, za katere je uporabnik prejel uspešen odgovor, tudi če te operacije ni imela časa, da bi se odrazila v shrambi strani na disku (že zgoraj. Opisano je bilo, da se dejansko pisanje v shrambo strani izvede v procesu, imenovanem "kontrolne točke", z nekaj zakasnitve ločenih niti).

Vnose v WAL delimo na logične in fizične. Logični so sami ključi in vrednosti. Fizično - odraža spremembe strani v trgovini strani. Medtem ko so logični zapisi lahko uporabni v nekaterih drugih primerih, so fizični zapisi potrebni samo za obnovitev v primeru zrušitve, zapisi pa so potrebni samo od zadnje uspešne kontrolne točke. Tu se ne bomo spuščali v podrobnosti in razlagali, zakaj tako deluje, zainteresirani pa se lahko obrnejo na že omenjeni članek na Apache Ignite Wiki: Ignite Persistent Store - pod pokrovom.

Pogosto obstaja več fizičnih zapisov na logični zapis. To pomeni, da na primer ena operacija vstavitve v predpomnilnik vpliva na več strani v pomnilniku strani (stran s samimi podatki, strani z indeksi, strani s prostimi seznami). V nekaterih sintetičnih testih sem ugotovil, da fizični zapisi zavzemajo do 90 % datoteke WAL. Vendar so potrebni za zelo kratek čas (privzeto je interval med kontrolnimi točkami 3 minute). Logično bi bilo, da bi se znebili teh podatkov, potem ko so izgubili relevantnost. Natančno to počne mehanizem stiskanja WAL: znebi se fizičnih zapisov in stisne preostale logične zapise z uporabo zip, medtem ko se velikost datoteke zelo močno zmanjša (včasih tudi za desetkrat).

Fizično je WAL sestavljen iz več segmentov (10 privzeto) fiksne velikosti (64 MB privzeto), ki so krožno prepisani. Takoj ko je trenutni segment zapolnjen, je naslednji segment dodeljen kot trenutni, zapolnjeni segment pa se prekopira v arhiv z ločeno nitjo. Zgoščevanje WAL že deluje z arhivskimi segmenti. Prav tako kot ločena nit spremlja izvajanje kontrolne točke in začne stiskanje v segmentih arhiva, za katere fizični zapisi niso več potrebni.

Stiskanje podatkov v Apache Ignite. Sberjeva izkušnja

Vpliv na uspešnost

Ker stiskanje WAL teče kot ločena nit, ne bi smelo imeti neposrednega vpliva na operacije, ki se izvajajo. Vendar še vedno dodatno obremenjuje procesor v ozadju (stiskanje) in disk (branje vsakega segmenta WAL iz arhiva in pisanje stisnjenih segmentov), ​​tako da bo, če sistem deluje z največjo zmogljivostjo, to povzročilo tudi poslabšanje zmogljivosti.

Kako omogočiti in konfigurirati

Zgoščevanje WAL lahko omogočite z lastnostjo WalCompactionEnabled в DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Poleg tega lahko z uporabo metode DataStorageConfiguration.setWalCompactionLevel() nastavite stopnjo stiskanja, če niste zadovoljni s privzeto vrednostjo (BEST_SPEED).

Stiskanje posnetkov strani WAL

Kako to deluje

Ugotovili smo že, da se v WAL zapisi delijo na logične in fizične. Za vsako spremembo vsake strani se v pomnilniku strani ustvari fizični zapis WAL. Tudi fizični zapisi so razdeljeni na 2 podvrsti: zapis posnetka strani in delta zapis. Vsakič, ko nekaj spremenimo na strani in jo prenesemo iz čistega v umazano stanje, se popolna kopija te strani shrani v WAL (page snapshot record). Tudi če smo spremenili samo en bajt v WAL, bo zapis nekoliko večji od velikosti strani. Če nekaj spremenimo na že umazani strani, se v WAL-u oblikuje delta zapis, ki odraža samo spremembe v primerjavi s prejšnjim stanjem strani, ne pa celotne strani. Ker se ponastavitev stanja strani iz umazanih v čiste izvede med postopkom kontrolne točke, bodo takoj po začetku kontrolne točke skoraj vsi fizični zapisi sestavljeni samo iz posnetkov strani (ker so vse strani takoj po začetku kontrolne točke čiste) , nato pa, ko se približamo naslednji kontrolni točki, delta zapisa delta začne rasti in se znova ponastavi na začetku naslednje kontrolne točke. Meritve v nekaterih sintetičnih testih so pokazale, da delež posnetkov strani v skupnem obsegu fizičnih zapisov dosega 90 %.

Ideja stiskanja posnetkov strani WAL je stiskanje posnetkov strani z že pripravljenim orodjem za stiskanje strani (glejte stiskanje strani na disku). Hkrati se v WAL zapisi shranjujejo zaporedno v načinu samo za dodajanje in ni potrebe po vezavi zapisov na meje blokov datotečnega sistema, zato tukaj, za razliko od mehanizma stiskanja strani diska, ne potrebujemo redkih datotek na vse; zato ta mehanizem ne bo deloval samo v OS Linux. Poleg tega nam ni več pomembno, koliko smo stran lahko stisnili. Tudi če smo sprostili 1 bajt, je to že pozitiven rezultat in lahko stisnjene podatke shranimo v WAL, za razliko od stiskanja strani diska, kjer stisnjeno stran shranimo le, če smo sprostili več kot 1 blok datotečnega sistema.

Strani so visoko stisljivi podatki, njihov delež v skupnem obsegu WAL je zelo visok, zato lahko brez spreminjanja formata datoteke WAL dosežemo znatno zmanjšanje njene velikosti. Stiskanje, vključno z logičnimi zapisi, bi zahtevalo spremembo formata in izgubo združljivosti, na primer za zunanje uporabnike, ki bi jih morda zanimali logični zapisi, vendar ne bi povzročilo znatnega zmanjšanja velikosti datoteke.

Tako kot pri stiskanju strani diska lahko tudi stiskanje posnetkov strani WAL uporablja algoritme stiskanja ZSTD, LZ4, Snappy, pa tudi način SKIP_GARBAGE.

Vpliv na uspešnost

Ni težko opaziti, da neposredno omogočanje stiskanja posnetkov strani WAL vpliva samo na niti, ki zapisujejo podatke v pomnilnik strani, torej na tiste niti, ki spreminjajo podatke v predpomnilnikih. Branje fizičnih zapisov iz WAL se zgodi samo enkrat, v trenutku, ko se vozlišče dvigne po padcu (in le, če pade med kontrolno točko).

To vpliva na niti, ki spreminjajo podatke na naslednji način: dobimo negativen učinek (CPE) zaradi potrebe po stiskanju strani vsakič pred zapisovanjem na disk in pozitiven učinek (disk IO) zaradi zmanjšanja količine podatki napisani. V skladu s tem je tukaj vse preprosto: če je zmogljivost sistema omejena s CPU, dobimo rahlo poslabšanje, če je omejena z diskovnim V/I, dobimo povečanje.

Posredno zmanjšanje velikosti WAL vpliva tudi (pozitivno) na tokove, ki odlagajo segmente WAL v arhiv in tokove stiskanja WAL.

Realni testi zmogljivosti v našem okolju z uporabo sintetičnih podatkov so pokazali rahlo povečanje (pretok se je povečal za 10%-15%, zakasnitev zmanjšala za 10%-15%).

Kako omogočiti in konfigurirati

Najmanjša različica Apache Ignite: 2.8. Omogočite in konfigurirajte na naslednji način:

  • V poti razreda mora obstajati modul ignite-compression. Privzeto se nahaja v distribuciji Apache Ignite v imeniku libs/optional in ni vključen v pot do razreda. Imenik lahko preprosto premaknete eno raven višje v libs in potem, ko ga zaženete prek ignite.sh, bo samodejno omogočen.
  • Vztrajnost mora biti omogočena (omogočeno prek DataRegionConfiguration.setPersistenceEnabled(true)).
  • Način stiskanja je treba nastaviti z metodo DataStorageConfiguration.setWalPageCompression(), je stiskanje privzeto onemogočeno (način DISABLED).
  • Po želji lahko nastavite stopnjo stiskanja z metodo DataStorageConfiguration.setWalPageCompression(), glejte javadoc za metodo za veljavne vrednosti za vsak način.

Zaključek

Obravnavani mehanizmi stiskanja podatkov v Apache Ignite se lahko uporabljajo neodvisno drug od drugega, sprejemljiva pa je tudi kakršna koli kombinacija le-teh. Razumevanje njihovega delovanja vam bo omogočilo, da ugotovite, kako primerni so za vaše naloge v vašem okolju in kaj boste morali žrtvovati pri njihovi uporabi. Stiskanje strani diska je zasnovano za stiskanje glavnega pomnilnika in lahko zagotovi srednje razmerje stiskanja. Stiskanje posnetkov strani WAL bo zagotovilo povprečno stopnjo stiskanja datotek WAL in bo najverjetneje celo izboljšalo zmogljivost. Zgoščevanje WAL ne bo imelo pozitivnega učinka na zmogljivost, vendar bo zmanjšalo velikost datotek WAL, kolikor je mogoče, z odstranitvijo fizičnih zapisov.

Vir: www.habr.com

Dodaj komentar