Suure andmemahtude töötamisel võib tekkida probleemide puudujäägis kettaruumis. Üks viis selle probleemi lahendamiseks on andmete kokkusurumine, mis võimaldab sama riistvara kasutades suurendada salvestusmahte. Selles artiklis vaatleme, kuidas andmete kokkusurumine Apache Ignite'is toimib. Artikkel keskendub ainult toote sisemiselt rakendatud kettas olevatele kokkusurumismeetoditele. Teised andmete kokkusurumise meetodid (võrgus, mälus), olgu need rakendatud või mitte, jäävad välja.
Nii et kui püsimood on sisse lülitatud, hakkab Ignite andmete muutmisel kettas salvestama:
- Vahemälu sisu
- Eelneva kirjutamise logi (Write Ahead Log, lühidalt WAL)
WAL-i kokkusurumiseks on juba pikka aega olemas mehhanism, mida nimetatakse WAL kokkusurumiseks. Hiljuti ilmunud Apache Ignite 2.8-s on lisaks sellele veel kaks mehhanismi, mis võimaldavad andmeid kettal kokku suruda: kettalehe kokkusurumine vahemälu sisu kokkusurumiseks ja WAL lehe hetkepiltide kokkusurumine mõnede WAL-kirjete kokkusurumiseks. Allpool on rohkem teavet nende kolme mehhanismi kohta.
Kettalehe kokkusurumine
Kuidas see töötab
Alustame lühidalt Ignite'i andmete salvestamise viisist. Salvestamiseks kasutatakse leheküljepõhist mälu. Lehe suurus määratakse sõlme käivitamise ajal ja seda ei saa hiljem muuta, samuti peab lehe suurus olema kahekordne ja vastama failisüsteemi ploki suurusele. Lehed laaditakse RAM-i kettalt vajadusel, andmemahu suurus kettal võib ületada eraldatud RAM-i mahtu. Kui RAM-is on lehe laadimiseks ruumipuudus, asendatakse vanad, enam mitte kasutatavad lehed RAM-ist.
Kettal salvestatakse andmed järgmisel viisil: iga vahemälu rühma partitsiooni jaoks luuakse eraldi fail, milles lehed järgnevad üksteisele kasvavas järjestuses indeksi järgi. Lehe täielik identifikaator sisaldab vahemälu rühma identifikaatorit, partitsiooni numbrit ja lehe indeksit failis. Seega saame lehe täieliku identifikaatori põhjal ühemõtteliselt määrata faili ja faili offset'i iga lehe jaoks. Täiendavat teavet leheküljepõhise mälu ülesehituse kohta leiate artiklist Apache Ignite Wiki: .
Disk page compression, nagu nimest järeldada võib, töötab lehe tasandil. Kui see mehhanism on aktiveeritud, toimub andmete töötlemine RAM-is nii nagu need on, ilma igasuguse kompressioonita, kuid pilti salvestades RAM-ist kõvakettale toimub nende tihendamine.
Kuid iga lehe eraldi tihendamine ei lahenda probleemi, tuleb leida viis, kuidas vähendada lõplikku andmefailide suurust. Kui lehe suurus ei ole enam fikseeritud, ei saa me lehti failidesse järjestikku kirjutada, sest see võib tekitada terve rea probleeme:
- Me ei saa lehe indeksi abil arvutada, kus leht asub failis.
- Pole selge, mida teha lehtedega, mis asuvad faili mitte lõpus ja muudavad oma suurust. Kui lehe suurus väheneb, kaob koht, mille ta vabastas. Kui lehe suurus suureneb, tuleb otsida talle juba uus koht failis.
- Kui leht nihkub failisüsteemi ploki suurusele mittevastavate baitide arvuga, siis selle lugemiseks või kirjutamiseks on vajalik puudutada ühte faili süsteemi plokki rohkem, mis võib põhjustada jõudluse langust.
Et neid probleeme mitte üksi lahendada, kasutab disk page compression Apache Ignite'is failisüsteemi mehhanismi, mida nimetatakse kõhnateks failideks. Kõhn (sparse) fail on selline fail, kus mõned, nullidega täidetud piirkonnad võivad olla märgitud kui «augud». See tähendab, et need augud ei nõua failisüsteemi plokkide eraldamist, mis omakorda säästab ketta ruumi.
Loogiliselt on, et failisüsteemi ploki vabastamiseks peab augude suurus olema suurem või vähemalt võrdne failisüsteemi ploki suurusega, mis seab täiendava piirangu Apache Ignite lehe suurusele: et tihendamine annaks mingit mõju, peab lehe suurus olema rangelt suurem, kui failisüsteemi ploki suurus. Kui lehe suurus on võrdne ploki suurusega, ei suuda me kunagi ühtegi plokki vabastada, kuna ühe ploki vabastamiseks peab tihendatud leht võtma 0 baiti. Kui lehe suurus on võrdne kahe või nelja ploki suurusega, saame vabastada vähemalt ühe ploki, kui meie leht tihendatakse vähemalt 50% või 75% vastavalt.
Seega, mehanismi töö järeldus on järgmine: kui lehte kirjutatakse kettale, proovib süsteem lehte pigistada. Kui pigistatud lehe suurus võimaldab vabastada ühe või enam failisüsteemi blokki, siis leht salvestatakse pigistatud kujul, vabastatud blokkide kohtadesse tehakse "auk" (täidetakse süsteemikõne fallocate() lipukesega "punch hole"). Kui pigistatud lehe suurus ei võimalda bloke vabastada, salvestatakse leht nii nagu on, pigistamata kujul. Kõik lehekülgede offsetid arvutatakse nagu ka ilma pigistamiseta, korrutades lehekülje indeksi lehekülje suurusega. Ükski lehekülgede ümberpaigutamine ei ole vajalik. Lehekülgede offsetid, nagu ka ilma pigistamiseta, langevad failisüsteemi blokki piiridesse.

Praeguses rakenduses suudab Ignite alusel ainult Linux OS-i kasutada sparse-faile, seega disk page compression saab lubada ainult Ignite'i kasutamisel selle operatsioonisüsteemi peal.
Disk page compression jaoks võivad olla kasutatavad pigistamisalgoritmid: ZSTD, LZ4, Snappy. Lisaks on töörežiim (SKIP_GARBAGE), kus lihtsalt visatakse mõttetu lehe koht välja, ilma et jääks pigistamist, mis vähendab CPU koormust võrreldes varem mainitud algoritmidega.
Mõju jõudlusele
Kahjuks ei ole ma reaalses keskkonnas jõudlust tegelikult mõõtnud, kuna meil ei ole kavas seda mehhanismi tootmises kasutada, kuid võime teoreetiliselt arutleda, kus me kaotame ja kus võidame.
Selleks peame meenutama, kuidas toimuvad lehekülgede lugemine ja kirjutamine järele pääsemise ajal:
- Lugemise toimingut teostades otsitakse lehekülge esmalt RAM-is, kui otsing ei õnnestu, laaditakse leht RAM-i kettalt sama lõime poolt, mis teostab lugemist.
- Kirjutamise toimingu korral märgitakse RAM-i leht mustaks, samas ei toimu füüsilist lehe salvestamist kettale kohe kirjutavat protsessi teostava lõime poolt. Kõik mustad lehed salvestatakse kettale hiljem checkpointi protsessi käigus eraldi lõime poolt.
Seega, mõjude lugemisoperatsioonide peale:
- Positiivne (disk I/O), vähendades loetud failisüsteemi blokkide arvu.
- Negatiivne (CPU), kuna täiendav koormus, mis on vajalik operatsioonisüsteemile sparse-failidega töötamiseks. Samuti võivad siin ilmneda täiendavad IO-operatsioonid keerukama sparse-failistruktuuri salvestamiseks (kõigi sparse-failide toimimise üksikasjadega ma, kahjuks, ei ole tuttav).
- Negatiivne (CPU), kuna lehtede dekompressioon on vajalik.
- Kirjutamisele mõju ei ole.
- Mõju kontrollpunkti protsessile (siin on kõik sarnane lugemisoperatsioonidega):
- Positiivne (disk IO), kuna väheneb kirjutatud blokkte arvu failisüsteemis.
- Negatiivne (CPU, võib-olla disk IO), kuna töötamine sparse-failidega.
- Negatiivne (CPU), kuna lehtede kokkusurumine on vajalik.
Kumb tass kaaludest ülekaalus on? See sõltub väga keskkonnast, kuid kaldun arvama, et disk-page kompressioon toob enamikus süsteemides pigem jõudluse halvenemise. Eriti kuna testid teistes andmebaasihaldurites, mis kasutavad sarnast lähenemist sparse-failidele, näitavad jõudluse langust, kui kompressioon on sisse lülitatud.
Kuidas sisse lülitada ja seadistada
Nagu juba ütlesin, minimaalne versioon Apache Ignite, mis toetab disk-page kompressiooni: 2.8 ja toetab ainult operatsioonisüsteemi Linux. Sisse lülitamine ja seadistamine toimub järgmiselt:
- Class-path'is peab olema moodul ignite-compression. Vaikimisi asub see Apache Ignite jaotises libs/optional ja ei kuulu class-path'i. Saate lihtsalt viia kausta ühe tasandi võrra ülespoole libs ja siis, kui käitate ignite.sh kaudu, lisatakse see automaatselt.
- Püsivus peab olema sisse lülitatud (sisse lülitatakse kaudu
DataRegionConfiguration.setPersistenceEnabled(true)). - Lehe suurus peab olema suurem kui failisüsteemi ploki suurus (saab määrata läbi
DataStorageConfiguration.setPageSize()). - Iga vahemälu juures, mille andmeid tuleb kokku suruda, peab konfigureerimisse seadistama kompressioonimeetodi ja (valikuliselt) kompressioonitaseme (meetodid
CacheConfiguration.setDiskPageCompression(), CacheConfiguration.setDiskPageCompressionLevel()).
WAL kompressioon
Kuidas see töötab
Mis on WAL ja miks see vajalik on? Väga lühidalt: see on ajakiri, kuhu jõuavad kõik sündmused, mis muudavad lõpuks lehe salvestust. Selle peamine eesmärk on võimaldada taastamist kahjude korral. Iga operatsioon peab enne juhtimise andmist kasutajale esmalt sündmuse WAL-i salvestama, et kahjude korral oleks võimalik ajakirja kaudu taastada kõik operatsioonid, mille puhul kasutaja sai eduka vastuse, isegi kui need operatsioonid ei saanud veel lehe salvestusse kettale kajastuda (ülal on juba kirjeldatud, et tegelik salvestamine lehe salvestusse toimub protsessis, mida nimetatakse „kontrollpunktiks“, teatud viivitusega läbi eraldi protsesside).
WAL-i kanded jagunevad loogilisteks ja füüsilisteks. Loogilised on ise võtmed ja väärtused. Füüsilised peegeldavad lehtede muudatusi lehe salvestuses. Kui loogilised kanded võivad olla kasulikud ka muudel juhtudel, siis füüsilised kanded on vajalikud ainult taastamiseks kahjude korral ja neid on vaja ainult alates viimase edukalt kontrollpunktist. Siin me ei kavatse detaile arutada ja selgitada, miks see nii töötab, kuid huvilised saavad pöörduda juba mainitud artikli poole Apache Ignite'i Vikis: .
Ühe loogilise kande kohta tekib tihti mitu füüsilist kande. Näiteks üks put-operatsioon vahemälus puudutab mitut lehte lehe mälus (leht, kus on andmed, lehed indeksitega, lehed free-listide jaoks). Mõnedes sünteetilistes testides on mul õnnestunud saavutada, et füüsilised kanded hõivasid kuni 90% WAL-faili mahust. Samas on need vajalikud väga lühikese aja jooksul (vaikimisi on kontrollpunktide vaheline intervall 3 minutit). Oleks loogiline, et kui need andmed kaotavad oma ajakohasuse, siis neist loobuda. Just seda teeb WAL-i kompaktsuse mehhanism, vabastab füüsilistest kanded ja kokku surub allesjäänud loogilised kanded zip-iga, samal ajal kui faili suurus väheneb väga oluliselt (mõnikord kümneid kordi).
Füüsiliselt koosneb WAL mitmest segmentist (vaikimisi 10) fikseeritud suurusega (vaikimisi 64Mb), mida üle kirjutatakse ringikaupa. Kui praegune segment on täis, määratakse järgmiseks segmendiks järgmine segment, ja täidetud segment kopeeritakse arhiivi eraldi voos. WAL kompaktsus töötab juba arhiivsegmentidega. Samuti jälgib see eraldi voos kontrolle ja alustab arhiivsegmentide tihendamist, mille füüsilised kirjed ei ole enam vajalikud.

Mõju jõudlusele
Kuna WAL kompaktsus töötab eraldi voos, ei tohiks see otse mõjutada teostatavaid operatsioone. Kuid see loob siiski lisakoormuse CPU-le (tihendamine) ja kettale (iga WAL segmendi lugemine arhiivist ja tihendatud segmentide kirjutamine), seega, kui süsteem töötab oma võimaluste piiril, võib see samuti põhjustada jõudluse langust.
Kuidas sisse lülitada ja seadistada
WAL kompaktsuse saab lubada atribuudi kaudu WalCompactionEnabled ja DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Samuti saab meetodi DataStorageConfiguration.setWalCompactionLevel() abil määrata tihendamise taseme, kui vaikimisi väärtus (BEST_SPEED) ei sobi.
WAL lehekülje snapshot tihendamine
Kuidas see töötab
Varem leidis, et WAL kirjed jagunevad loogilisteks ja füüsilisteks. Iga muudatus iga lehe kohta lehe mälus genereerib füüsilise WAL kirje. Füüsilised kirjed jagunevad omakorda kaheks alaliigiks: lehe hetkeseisu kirjed ja delta kirjed. Iga kord, kui midagi lehe peal muudame ja muudame selle puhtast seisundist määrdunudks, salvestatakse WAL-is selle lehe täieoige koopia (lehe hetkeseisu kirje — lehe snehšot). Isegi kui me muutsime vaid ühte baitit, salvestatakse WAL-is kirje, mis on veidi suurem kui lehe suurus. Kui me aga muudame midagi juba määrdunud lehel, genereerib WAL delta kirje, kus on kajastatud ainult muudatused võrreldes lehe eelmise seisundiga, kuid mitte kogu lehe sisu. Kuna lehtede seisundi taastamine määrdunudlt puhtaks toimub kontrollpunkti protsessis, siis pärast kontrollpunkti algust koosneb peaaegu kõik füüsilised kirjed vaid lehe snehšotitest (kuna kõik lehed on pärast kontrollpunkti algust puhtad), seejärel, mida lähemale järgmisele kontrollpunktile me jõuame, hakkavad delta kirjed suurendama oma osakaalu ja taas nullitakse järgmise kontrollpunkti alguses. Mõnedes sünteetilistes testides on näidatud, et lehe snehšotide osakaal füüsiliste kirje kogumahus ulatub 90%.
WAL lehe snehšoti kokkutõmbumise idee seisneb selles, et tihendada lehe snehšoteid, kasutades olemasolevat tööriista lehtede tihendamiseks (vt disk page compression). Samas salvestatakse WAL kirjed järjestikku append-only režiimis, seega ei ole kirjeid vaja siduda failisüsteemi plokkide piiridega, mistõttu ei ole meil siin, erinevalt disk page compression mehhanismist, nõutavad siserakendused, vastavalt toimib see mehhanism mitte ainult Linuxi operatsioonisüsteemides. Lisaks pole me enam mures selle üle, kui palju me suudame lehte tihendada. Isegi kui me vabastasime 1 baidi, on see juba positiivne tulemus ja võime salvestada WAL-i tihendatud andmeid, erinevalt disk page compressionist, kus me salvestame tihendatud lehe ainult siis, kui vabastasime rohkem kui 1 failisüsteemi ploki.
Leheküljed on hästi kompressitavad andmed, nende osakaal WAL-i kogumahus on väga kõrge, seega saame, muutes WAL-faili formaati, märkimisväärselt vähendada selle suurust. Kompressioon, sealhulgas loogiliste salvestiste puhul, nõuaks formaadi muutmist ja ühilduvuse kaotamist, näiteks välistarbijate jaoks, keda võivad huvitada loogilised salvestised, samas ei tooks see märkimisväärset vähendamist faili maht.
Nii nagu disk page compression’i puhul, saab WAL page snapshot compression’i jaoks kasutada ka ZSTD, LZ4, Snappy kompressiooni algoritme ning SKIP_GARBAGE režiimi.
Mõju jõudlusele
Kuidas pole raske märgata, et WAL page snapshot compression’i otsene lubamine mõjutab ainult vooge, mis salvestavad andmeid lehe mällu, st neid vooge, mis muudavad andmeid vahemäludes. WAL-i füüsiliste salvestiste lugemine toimub ainult ühekordselt, hetkel sõlme tõstmisel pärast kokkuvarisemist (ja ainult juhul, kui kokkuvarisemine toimub kontrollpunkti protsessis).
Andmete muutmise voogudele mõjub see järgmiselt: saame negatiivse efekti (CPU) tänu igal korral lehe kompressimise vajalikule päringule enne ketas kirjutamist ja positiivse efekti (disk IO) tänu salvestatud andmete vähenemisele. Selle tulemusena on siin kõik lihtne: kui süsteemi jõudlus sõltub CPU-st, saame väikese halvenemise, kui ketas sisestamisest/väljastamisest — saame kasvu.
Kaudselt mõjutab WAL-i suuruse vähenemine ka positiivselt vooge, mis arhiivivad WAL-segmente ja WAL-i tihendamise vooge.
Reaalsed jõudlustestid meie keskkonnas sünteetiliste andmete põhjal näitasid väikest kasvu (läbivood 10%-15% ja latentsus vähenes 10%-15%).
Kuidas sisse lülitada ja seadistada
Apache Ignite miinimumversioon: 2.8. Lubamine ja seadistamine toimub järgmiselt:
- Class-path'is peab olema moodul ignite-compression. Vaikimisi asub see Apache Ignite jaotises libs/optional ja ei kuulu class-path'i. Saate lihtsalt viia kausta ühe tasandi võrra ülespoole libs ja siis, kui käitate ignite.sh kaudu, lisatakse see automaatselt.
- Püsivus peab olema sisse lülitatud (sisse lülitatakse kaudu
DataRegionConfiguration.setPersistenceEnabled(true)). - Tuleb määrata kompressioonirežiim meetodi kaudu
DataStorageConfiguration.setWalPageCompression(), vaikimisi on kompressioon välja lülitatud (režiim DISABLED). - Valikuliselt saab seadistada kompressiooni astet meetodi kaudu
DataStorageConfiguration.setWalPageCompression(), lubatud väärtused iga režiimi jaoks vaata meetodi javadoc-ist.
Kokkuvõte
Apache Ignite'is arutatud andmekompressioonimehhanisme saab kasutada sõltumatult üksteisest, kuid lubatud on ka nende kombinatsioonid. Nende tööpõhimõtete mõistmine aitab määrata, kui hästi need sobivad teie ülesannetele teie keskkonnas ning millest tuleb nende kasutamisel loobuda. Disk page compression on mõeldud põhitallendi kompressiooniks ja võib pakkuda keskmist kompressioonitaset. WAL page snapshot compression pakub keskmist kompressioonitaset WAL-failide jaoks, samas kui see tõenäoliselt isegi parandab jõudlust. WAL compaction ei mõjuta jõudlust positiivselt, kuid vähendab maksimaalselt WAL-failide suurust füüsiliste kirjete eemaldamise kaudu.
Allikas: habr.com
