Suurtel andmete kogustel töötades võib mõnikord tekkida teravalt vajadus kettaruumi järele. Üks lahendus sellele probleemile on tihendamine, mis võimaldab samadel seadmetel suurendada salvestusmahtu. Selles artiklis vaatleme, kuidas andmete tihendamine töötab Apache Ignite'is. Artiklis käsitletakse ainult toote sees rakendatud kettas tihendamise meetodeid. Muud andmete tihendamise viigid (võrgu kaudu, mälus), olgu need rakendatud või mitte, jäävad artikli raadiusest välja.
Nii et, kui persistence režiim on sisse lülitatud, hakkab Ignite andmete muutmisel vahemälu kirjutama kettale:
- Vahemälu sisu
- Eelnevate kirjutiste ajakiri (Write Ahead Log, edaspidi lihtsalt WAL)
WAL tihendamiseks on juba mõnda aega olemas mehhanism, mida nimetatakse WAL tihendamiseks. Hiljuti ilmunud Apache Ignite 2.8 toob kaasa veel kaks mehhanismi, mis võimaldavad tihendada andmeid kettas: need on disk page compression vahemälu sisu tihendamiseks ja WAL page snapshot compression mõnede WAL kirjeid tihendamiseks. Kõikidest kolmest mehhanismist saad lähemalt lugeda allpool.
Disk page compression
Kuidas see toimib
Alustuseks räägime lühidalt, kuidas Ignite andmeid salvestab. Salvestamiseks kasutatakse lehemälu. Lehe suurus määratakse sõlme alguses ja seda ei saa hiljem muuta, samuti peab lehe suurus olema kahe astme ja olema failisüsteemi ploki suurusega jagatav. Lehed laaditakse RAM-i diskilt vastavalt vajadusele; andmete suurus diskil võib ületada eraldatud RAM-i mahtu. Kui RAM-is pole piisavalt ruumi, et laadida lehte diskilt, tõrjutakse RAM-ist välja vanad, enam mitte kasutatavad lehed.
Diskil salvestatakse andmed järgmisel viisil: iga vahepartitsiooni jaoks iga vahegrupi jaoks luuakse eraldi fail, mille sees on lehed järjestatud indeksite tõusvas järjekorras. Lehe täisidentifikaator sisaldab vahegrupi identifikaatorit, partitsiooni numbrit ja lehe indeksi faili sees. Seega saame lehe täisidentifikaatori abil üheselt määrata faili ja failis oleva ofseti iga lehe jaoks. Üksikasjalikumalt lehe mälu ülesehituse kohta saab lugeda artiklist Apache Ignite Wiki: .
Disk page compression mechanism, as the name suggests, operates at the page level. When this mechanism is enabled, data in RAM is managed without any compression, but when saving pages from RAM to disk, compression takes place.
However, compressing each page separately is not the solution to the problem; we need to find a way to reduce the size of the resulting data files. If the page size is no longer fixed, we can’t write pages one after another into a file, as this may lead to a series of issues:
- We won’t be able to calculate the offset for a page’s position in the file using the page index.
- It’s unclear how to handle pages that are not at the end of the file and are changing size. If the size of a page decreases, the space it freed is lost. If the page size increases, a new space in the file will need to be found for it.
- Kui lehekülg nihkub failisüsteemi ploki suurusele mittetäiendava arvu baitide võrra, tuleb selle lugemiseks või kirjutamiseks puudutada ühte plokki rohkem, mis võib põhjustada jõudluse halvenemist.
Probleemide lahendamiseks ei pea te ise disk page compression meetodit kasutama, Apache Ignite kasutab failisüsteemi mehhanismi, mida nimetatakse sparse failideks. Sparse (haruldane) fail on fail, mille mõned nullidega täidetud piirkonnad võivad olla märgitud "augudeks". Sellega ei eraldata failisüsteemi plokke nende aukude salvestamiseks, mille tulemuseks on diskiruumi kokkuhoid.
On loogiline, et kui soovime vabastada failisüsteemi ploki, peab augu suurus olema vähemalt sama suur kui failisüsteemi plokk. See seab täiendava piiri lehe suurusele Apache Ignite'is: et kompressioon oleks tõhus, peab lehe suurus olema rangelt suurem kui failisüsteemi ploki suurus. Kui lehe suurus on sama nagu ploki suurus, ei saa me kunagi vabastada mitte ühtegi plokki, kuna ühe ploki vabastamiseks peab kokku pressitud leht võtma 0 bait. Kui lehe suurus on kaks või neli plokki, saame vabastada vähemalt ühe ploki, kui meie leht vahest 50% või 75% võrra kokku surutakse.
Seega on mehhanismi töö kokkuvõtteks: lehe salvestamisel kettale üritatakse lehte kokku suruda. Kui kokku surutud lehe suurus võimaldab vabastada ühe või enam failisüsteemi plokki, salvestatakse leht kompressitud kujul ning vabastatud plokkide kohale tekib "auku" (teostatakse süsteemikõne). fallocate() lipukesega „punch hole”). Kui tihendatud lehe suurus ei võimalda bloke vabastada, säilib leht nii nagu on, tihendamata kujul. Kõiki lehe offset'e arvestatakse nagu ilma tihendamiseta, lehe indeksi ja lehe suuruse korrutamisena. Lehtede üleviimist ei ole vaja käsitsi teha. Lehe offset'id nagu ka ilma tihendamiseta langevad failisüsteemi plokkide piiridesse.

Praeguses rakenduses suudab Ignite töötada sparse-failidega ainult Linuxi opsüsteemis, seega disk page compression saab olla lubatud ainult Ignite kasutamisel sellel opsüsteemil.
Squeeze algoritmid, mida saab kasutada disk page compression jaoks: ZSTD, LZ4, Snappy. Lisaks on olemas töörežiim (SKIP_GARBAGE), kus visatakse lihtsalt lehe kasutamata koht minema ilma tihendamise rakendamiseta ülejäänud andmetele, mis võimaldab vähendada CPU koormust võrreldes eelnevalt nimetatud algoritmidega.
Mõju jõudlusele
Kahjuks ei ole ma tegelikku jõudluse mõõtmist reaalses keskkonnas teostanud, kuna meil ei ole plaanis seda mehaanismi tootmises kasutada, kuid saame teoreetiliselt arutleda, kus me kaotame ja kus võidame.
Selleks peame meeles pidama, kuidas lehtede lugemine ja kirjutamine toimub nendele pöördumisel:
- Lugemisoperatsiooni läbiviimisel otsitakse see esmalt RAM-ist, ja kui otsing ebaõnnestub, laaditakse leht RAM-i diskilt sama voolu kaudu, mis teostab lugemist.
- Kirjutamisoperatsiooni korral märgitakse leht RAM-is kui 'must', samas ei toimu füüsiline lehe salvestamine diskile kohe kirjutava voolu käigus. Kõik mustad lehed salvestatakse hiljem diskile kontrollpunkti käigus eraldi voolude kaudu.
Seega on mõju lugemisoperatsioonidele:
- Positiivne (disk IO), tänu failisüsteemi loetud blokki arvu vähenemisele.
- Negatiivne (CPU), kuna operatsioonisüsteem nõuab sparsfailidega töötamiseks täiendavat koormust. Samuti võivad siin ilmneda täiendavad IO-operatsioonid, et salvestada keerulisemat sparsfaili struktuuri (kõigi sparsfailide töödetailidega ma kahjuks tuttav ei ole).
- Negatiivne (CPU), kuna lehtede dekompressioon on vajalik.
- Kirjutamisoperatsioonidele mõju ei ole.
- Mõju kontrollpunktiprotsessile (siin on kõik sarnane lugemisoperatsioonidega):
- Positiivne (disk IO), kuna vähendab failisüsteemi kirjutatud blokke.
- Negatiivne (CPU, võimalik, et disk IO), kuna töötamine sparsfailidega.
- Negatiivne (CPU), kuna lehtede tihendamine on vajalik.
Milline kaalukauss kaldub? See sõltub väga palju keskkonnast, kuid olen kaldunud arvama, et diskilehe tihendamine toob enamikus süsteemides pigem jõudluse halvenemise. Eelkõige, et testid teistes andmebaasides, mis kasutavad sarnast lähenemist sparsfailidele, näitavad jõudluse langust tihendamise sisse lülitamisel.
Kuidas lubada ja seadistada
Nagu juba mainitud, on minimaalne Apache Ignite versioon, mis toetab disk page compression: 2.8 ja seda toetatakse ainult Linuxi opsüsteemis. Selle sisselülitamine ja seadistamine toimub järgmiselt:
- Class-pathis peab olema moodul ignite-compression. Vaikimisi asub see Apache Ignite jaotises libs/optional ja ei kuulu class-pathi. Saa lihtsalt viia kataloog ühe taseme võrra ülespoole libs'i ja siis, käivitades ignite.sh, ta lisatakse automaatselt.
- Persistence peab olema sisse lülitatud (Selle saab sisselülitada läbi
DataRegionConfiguration.setPersistenceEnabled(true)). - Lehe suurus peab olema suurem kui failisüsteemi ploki suurus (seda saab määrata läbi
DataStorageConfiguration.setPageSize()). - Iga vahekogule, mille andmeid tuleb tihendada, tuleb seadistada tihendamise meetod ja (valikuliselt) tihendamise tase (meetodid
CacheConfiguration.setDiskPageCompression(), CacheConfiguration.setDiskPageCompressionLevel()).
WAL tihendamine
Kuidas see toimib
Mis on WAL ja milleks see vajalik on? Väga lühidalt: see on ajakiri, kuhu salvestatakse kõik sündmused, mis lõpuks muudavad lehe salvestust. Seda kasutatakse eelkõige selleks, et võimaldada taastumist, kui midagi läheb valesti. Iga operatsioon peab enne kasutajale juhtimise andmist esmalt salvestama sündmuse WAL-i, et juhul, kui midagi läheb valesti, oleks võimalik ajakirja järgi taastada kõik operatsioonid, mille osas kasutaja sai eduka vastuse, isegi kui need operatsioonid ei jõudnud veel lehe salvestusse kõvakettale (ülal on juba selgitatud, et tegelik salvestamine lehe salvestusse toimub protsessis, mida nimetatakse „kontrollpunktiks”, teatud viivitusega eraldi niitide poolt).
WAL-i salvestatud kirjed jagunevad loogilisteks ja füüsilisteks. Loogilised on võtmed ja väärtused ise. Füüsilised peegeldavad muudatusi lehtedes lehe salvestuses. Kuigi loogilised kirjed võivad olla kasulikud ka muudel juhtudel, on füüsilised kirjed vajalikud ainult taastamiseks pärast tõrke ilmnemist ning neid on vaja alates viimasest eduka kontrollpunkti hetkest. Siin me ei süvene üksikasjadesse ega selgita, miks see just nii toimib, kuid huvilised võivad pöörduda juba mainitud artikli poole Apache Ignite Wiki's: .
Ühe loogilise kirje kohta on sageli mitu füüsilist kirjet. See tähendab, et näiteks üks put-operatsioon vahemälus mõjutab mitut lehte lehte mälus (leht, kus on andmed, lehed indeksite jaoks, lehed vabade loendite jaoks). Mõnedel sünteetilistel testidel näitas mu tulemused, et füüsilised kirjed moodustasid kuni 90% WAL-faili mahust. Samas on need vajalikud väga lühikeseks ajaks (vaikimisi on ajavahemik kontrollpunktide vahel 3 minutit). Loogiliselt oleks need andmed, pärast nende asjakohasuse kadumist, eemaldada. Just seda teostab WAL compaction mehhanism, vabastades füüsilisi kirjeid ja tihendades zipiga allesjäänud loogilised kirjed, samas kui faili suurus väheneb märgatavalt (mõnikord kümneid kordi).
Füüsiline WAL koosneb mitmest fikseeritud suurusega segmentidest (vaikimisi 10, suurus 64MB), mis kirjutatakse ringikujuliselt üle. Kui praegune segment on täis, määratakse järgmiseks segmendiks järgmine, ja täidetud segment kopeeritakse arhivi eraldi voos. WAL compaction töötab juba arhiveeritud segmentidega. Samuti jälgib see eraldi voos kontrollpunkti täitmist ja alustab arhiveeritud segmentide tihendamist, füüsilised kirjed, millele ei ole enam vajadust.

Mõju jõudlusele
Kuna WAL compaction töötab eraldi voos, ei tohiks see otse mõjutada teostatavaid operatsioone. Kuid see annab siiski täiendava taustkoormuse CPU-le (tihendamine) ja kettale (iga WAL segment arhivist lugemine ja tihendatud segmentide kirjutamine), seega kui süsteem töötab oma piiride lähedal, võib see samuti põhjustada tulemuslikkuse langust.
Kuidas lubada ja seadistada
WAL compaction'i saab aktiveerida omaduse WalCompactionEnabled ühes DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Samuti saate meetodi DataStorageConfiguration.setWalCompactionLevel() abil määrata tihendamise taseme, kui vaikimisi väärtus (BEST_SPEED) ei sobi.
WAL lehe snapshot tihendamine
Kuidas see toimib
Oleme juba varasemalt välja selgitanud, et WAL-i kirjed jagunevad loogilisteks ja füüsilisteks. Iga muudatus iga lehe lehemälu vormistatakse füüsiliseks WAL-kirjeks. Füüsilised kirjed jagunevad omakorda kaheks alamtüübiks: lehe snapshot-kiri ja delta-kiri. Iga kord, kui me midagi lehe peal muudame ja muudame selle puhta seisundi määrdunudks, salvestatakse WAL-is täielik koopia sellest lehe peast (lehe snapshot-kiri — lehe sсhnapshot). Isegi kui me muudame ainult ühe bait, salvestatakse WAL-i kirjena, mille suurus on veidi suurem kui lehe suurus. Kui me muudame midagi juba määrdunud lehe peal, siis vormitakse WAL-is delta-kiri, milles kajastuvad ainult muudatused võrreldes lehe varasema seisundiga, kuid mitte kogu leht täielikult. Kuna määrdunud lehtede olek puhtaks vahetatakse kontrollpunkti protsessi käigus, siis pärast kontrollpunkti algust koosnevad peaaegu kõik füüsilised kirjed ainult lehtede sсhsnapshot-kirjadest (kuna kõik lehed on kontrollpunkti alguses puhtad), seejärel lähenedes järgmisele kontrollpunktile hakkab delta-kirjade osakaal kasvama ja taas nullitakse järgmise kontrollpunkti alguses. Mõnedel sünteetilistel testidel on mõõtmised näidanud, et lehtede snapshot-kirjade osakaal füüsilistes kirjedes ulatub kuni 90%.
WAL-i lehekülje kohandatud kompressiooni idee seisneb lehekülgede kompressimises, kasutades juba olemasolevat tööriista lehekülgede kompressimiseks (vt disk page compression). WAL-i kirjed salvestatakse järjestikku append-only režiimis, ilma et oleks vaja siduda kirjeid failisüsteemi plokkide piiridega, seega erinevalt disk page compression mehhanismist ei ole meil selles osas vajadust sparse-failide järele, mistõttu see mehhanism töötab ka mitte ainult Linuxi operatsioonisüsteemidel. Lisaks ei ole me enam nii mures, kui palju me suudame lehekülge kokku suruda. Isegi kui vabastame 1 bait, on see juba positiivne tulemus ja saame SAL-i salvestada komprimeeritud andmed, erinevalt disk page compression-ist, kus salvestame komprimeeritud lehekülje ainult juhul, kui oleme vabastanud rohkem kui 1 ploki failisüsteemist.
Leheküljed on hästi kokkuvõetavad andmed ja nende osakaal WAL-i kogumahus on väga kõrge, seega saame WAL-faili formaati muutmata saavutada märkimisväärse suuruse vähenemise. Loogiliste kirjade kokkuvõte nõuaks samuti formaadi muutmist ja ühilduvuse kaotamist, näiteks välistele tarbijatele, kellele loogilised kirjed võivad huvi pakkuda, ilma et see tooks üleliigset mahu vähenemist.
Nii nagu diskilehe kokkusurumiseks, võivad WAL-lehe momentfotosid kokkuvõtmiseks kasutada ZSTD, LZ4, Snappy kokkusurutuse algoritme ning ka režiimi SKIP_GARBAGE.
Mõju jõudlusele
Kuidas ei oleks lihtne märgata, et WAL-lehe momentfotosid kokkusurumine mõjutab otse vaid vooge, mis kirjutavad andmeid lehekülje mälu, nimelt neid vooge, mis muudavad andmeid vahemälus. Füüsiliste kirjete lugemine WAL-ist toimub ainult ühekordselt, nodi tõstmise hetkel pärast tõusu (ja ainult juhul, kui tõus toimus kontrollimise protsessis).
Andmete voogude muutmine mõjutab seda järgmiselt: saame negatiivse efekti (CPU) vajadusest iga kord enne andmete salvestamist kettale lehte tihendada ja positiivse efekti (disk IO) salvestatavate andmete hulga vähendamisest. Seega on siin kõik lihtne: kui süsteemi jõudlus sõltub CPU-st, tekib kerge halvenemine, kui aga kettasisendi/väljundi pealt — saame kasu.
Kaudne WAL-i suuruse vähenemine mõjutab samuti (positiivselt) vooge, mis arhiveerivad WAL-segmente ja WAL kompaktsuse vooge.
Reaalsed jõudlustestid meie keskkonnas sünteetiliste andmetega näitasid väikest tõusu (läbivool kasvas 10%-15%, latentsus vähenes 10%-15%).
Kuidas lubada ja seadistada
Apache Ignite minimaalne versioon: 2.8. Häälestamine ja seadistamine toimub järgmiselt:
- Class-pathis peab olema moodul ignite-compression. Vaikimisi asub see Apache Ignite jaotises libs/optional ja ei kuulu class-pathi. Saa lihtsalt viia kataloog ühe taseme võrra ülespoole libs'i ja siis, käivitades ignite.sh, ta lisatakse automaatselt.
- Persistence peab olema sisse lülitatud (Selle saab sisselülitada läbi
DataRegionConfiguration.setPersistenceEnabled(true)). - Kokkulepe tihendamise režiimi määramiseks peab olema antud meetodi abil
DataStorageConfiguration.setWalPageCompression(), vaikimisi on tihendamine välja lülitatud (režiim DISABLED). - Valikuliselt saab väljatöötatakse tihendamise astet meetodi abil
DataStorageConfiguration.setWalPageCompression(), lubatud väärtused iga režiimi jaoks vaata meetodi javadoc'ist.
Kokkuvõte
Apache Ignite'i andmekompressioonimehhanisme saab kasutada sõltumatult üksteisest, kuid lubatud on ka mis tahes nende kombinatsioon. Nende tööpõhimõtete mõistmine aitab määrata, kuivõrd need sobivad teie ülesannete jaoks teie keskkonnas ja mille nimel peate nende kasutamisel loobuma. Disk page compression on mõeldud peamise salvestuse kompressimiseks ja võib anda keskmise määraga kompressiooni. WAL page snapshot compression annab keskmise kompressioonimäära WAL-failide puhul, samas kui tõenäoliselt suurendab see isegi jõudlust. WAL kompaktne töötlus ei mõjuta jõudlust positiivselt, kuid vähendab maksimaalselt WAL-failide suurust füüsiliste kirjete eemaldamise kaudu.
Allikas: habr.com
