Strādājot ar lieliem datu apjomiem, reizēm var rasties problēmas ar vietas trūkumu diskos. Viena no šīm problēmām risināšanas metodēm ir saspiešana, kas ļauj, izmantojot to pašu aprīkojumu, palielināt uzglabāšanas apjomus. Šajā rakstā mēs aplūkosim, kā darbojas datu saspiešana Apache Ignite. Rakstā tiks aprakstītas tikai produktā iekļautās diskā veiktās saspiešanas metodes. Citi datu saspiešanas veidi (tīklā, atmiņā), gan realizētie, gan nē, paliks ārpus šī raksta.
Tātad, ieslēdzot persistence režīmu, datu izmaiņu rezultātā kešos, Ignite sāk ierakstīt diskā:
- Kešu saturs
- Aizņēmuma rakstīšanas žurnāls (Write Ahead Log, turpmāk WAL)
WAL saspiešanai jau ilgu laiku pastāv mehānisms, ko sauc par WAL kompresiju. Jaunākajā Apache Ignite 2.8 versijā ir pievienoti vēl divi mehānismi, kas ļauj saspiež datus diskā: tas ir disk page compression kešu satura saspiešanai un WAL page snapshot compression dažādu WAL ierakstu saspiešanai. Sīkāk par šiem trim mehānismiem zemāk.
Disk page compression
Efemerāli vispārējie mākonīši
Vispirms ļoti īsi apskatīsim, kā Ignite glabā datus. Glabāšanai tiek izmantota lapu atmiņa. Lapas izmērs tiek noteikts mezgla palaišanas brīdī un to nevar mainīt vēlākos posmos, kā arī lapas izmēram jābūt spēka divniekam un dalāmam ar failu sistēmas bloka izmēru. Lapas tiek ielādētas RAM no diska pēc vajadzības, datu apjoms diskā var pārsniegt rezervēto RAM apjomu. Ja RAM trūkst, lai ielādētu lapu no diska, vecās, vairs neizmantojamās lapas tiks izdzēstas no RAM.
Diskā dati tiek glabāti šādā veidā: katram katras kešgrupas partīcijas izveido atsevišķu failu. Šajā failā, paaugstinātas indeksācijas secībā, viena aiz otras seko lapas. Pilns lapas identifikators satur kešgrupas identifikatoru, partīcijas numuru un lapas indeksu failā. Tādējādi, izmantojot pilno lapas identifikatoru, mēs varam skaidri noteikt failu un ofsetu failā katrai lapai. Sīkāk par lapu atmiņas struktūru var izlasīt rakstā Apache Ignite Wiki: .
Disk page compression mehānisms, kā var nojaust no nosaukuma, darbojas lapu līmenī. Ieslēdzot šo mehānismu, darbs ar datiem RAM tiek veikts tā kā ir, bez jebkādas saspiešanas, taču brīdī, kad lapas tiek saglabātas no RAM uz disku, notiek to saspiešana.
Tomēr katras lapas saspiešana atsevišķi vēl nav risinājums problēmai, ir nepieciešams arī samazināt gala failu ar datiem izmēru. Ja lapas izmērs vairs nav fiksēts, mēs nevaram rakstīt lapas failā vienu aiz otras, jo tas var radīt virkni problēmu:
- Mēs nevarēsim ar lapu indeksu aprēķināt ofsetu, kurā tā atrodas failā.
- Nav skaidrs, ko darīt ar lapām, kas atrodas ne tikai faila beigās un maina savu izmēru. Ja lapas izmērs samazinās, vieta, ko tās atbrīvo, tiek zaudēta. Ja lapas izmērs palielinās, tai vairs būs jāmeklē jauna vieta failā.
- Ja lapa pārvietojas uz skaitli, kas nav dalāms ar failu sistēmas bloka izmēru, tās lasīšanai vai ierakstīšanai būs nepieciešams piekļūt par vienu failu sistēmas bloku vairāk, kas var izraisīt veiktspējas pasliktināšanos.
Lai nerisinātu šīs problēmas savā līmenī, disk page compression Apache Ignite izmanto failu sistēmas mehānismu, ko sauc par sparse failiem. Sparse (retināts) fails — tas ir fails, kurā dažas, ar nullēm aizpildītas reģioni var tikt atzīmēti kā „caurumi“. Šajā gadījumā failu sistēmas blokiem, lai saglabātu šos caurumus, netiks piešķirts nekas, tādējādi panākot vietas ietaupījumu diskā.
Loģiski, ka, lai atbrīvotu failu sistēmas bloku, cauruma izmēram jābūt lielākam vai vienādam ar failu sistēmas bloka izmēru, kas nosaka papildu ierobežojumu Apache Ignite lapas izmēram: lai saspiešana sniegtu vismaz kādu efektu, lapas izmēram jābūt stingri lielākam par failu sistēmas bloka izmēru. Ja lapas izmērs būs vienāds ar bloka izmēru, mēs nekad nevarēsim atbrīvot nevienu bloku, jo, lai atbrīvotu vienu bloku, saspiešanai jāaizņem 0 baitus. Ja, tomēr, lapas izmērs būs vienāds ar 2 vai 4 blokiem, mēs jau varēsim atbrīvot vismaz vienu bloku, ja mūsu lapa tiks saspiežama vismaz līdz 50% vai 75% attiecīgi.
Tādējādi mehānisma darbības galīgais apraksts: Ierakstot lapu diskā, tiek veikta mēģinājums saspiest lapu. Ja saspiestās lapas izmērs ļauj atbrīvot vienu vai vairākas failu sistēmas blokas, lapa tiek ierakstīta saspiestā veidā, atbrīvoto bloku vietā tiek izveidota "caurums" (izpildīts sistēmas izsaukums fallocate() ar “punch hole” flag). Ja saspiestās lapas izmērs neļauj atbrīvot blokas, lapa tiek saglabāta tāpat kā ir, nesaspiestā veidā. Visi lapu offseti tiek aprēķināti tāpat kā bez kompresijas, reizinot lapas indeksu ar lapas izmēru. Nav nepieciešama nekādu lapu relokācija pašam. Lapu offseti, tāpat kā bez kompresijas, iekļaujas failu sistēmas bloku robežās.

Pašreizējā Ignite realizācija spēj strādāt ar sparse failiem tikai uz Linux operētājsistēmas, attiecīgi disk page compression var tikt ieslēgta tikai, lietojot Ignite šajā operētājsistēmā.
Saspiešanas algoritmi, kurus var izmantot disk page compression: ZSTD, LZ4, Snappy. Turklāt ir darbības režīms (SKIP_GARBAGE), kurā tiek izslēgts tikai neizmantotais lapas telpas daļa bez kompresijas pārējiem datiem, kas ļauj samazināt slodzi uz CPU salīdzinājumā ar iepriekš minētajiem algoritmiem.
Ietekme uz veiktspēju
Diemžēl es neesmu veicis faktisko veiktspējas mērījumu uz reāliem stendiem, jo mēs neplānojam izmantot šo mehānismu ražošanā, taču varam teorētiski apspriest, kur mēs zaudēsim un kur iegūsim.
Tāpēc mums ir jāatceras, kā tiek veikta lapu lasīšana un rakstīšana, piekļūstot tām:
- Veicot lasīšanas operāciju, vispirms tiek meklēts tās RAM, ja meklēšana nav veiksmīga, lapa tiek ielādēta RAM no diska ar to pašu pavedienu, kas veic lasīšanu.
- Veicot rakstīšanas operāciju, lapa RAM tiek atzīmēta kā netīra, savukārt fiziskais lapa saglabāšana diskā neizdodas tajā pašā pavedienā, kurš veic rakstīšanu. Visas netīrās lapas tiek saglabātas diskā vēlāk procesa checkpoint laikā ar atsevišķiem pavedieniem.
Tādējādi ietekme uz lasīšanas operācijām:
- Pozitīva (disk IO), pateicoties lasīto failu sistēmas bloku skaita samazināšanai.
- Negatīvs (CPU), jo papildu slodze, kas nepieciešama operētājsistēmai, lai strādātu ar sparse failiem. Šeit var rasties papildu IO operācijas, lai saglabātu sarežģītāku sparse failu struktūru (ar visām sparse failu darbības detaļām es, diemžēl, neesmu pazīstams).
- Negatīvs (CPU), jo ir nepieciešama lapu dekompresija.
- Uz rakstīšanas operācijām tas neietekmē.
- Ietekme uz checkpointra procesu (šeit viss ir līdzīgi lasīšanas operācijām):
- Pozitīvs (disk IO), samazinot rakstīto failu sistēmas bloku skaitu.
- Negatīvs (CPU, iespējams, disk IO), jo ir darbs ar sparse failiem.
- Negatīvs (CPU), jo ir nepieciešama lapu saspiešana.
Kurā svaru kausā pārsvers? Tas viss ļoti atkarīgs no vidējā, bet es esmu nosliecies uz to, ka disk page compression drīzāk novedīs pie veiktspējas samazināšanās lielākajā daļā sistēmu. Turklāt citu DBMS testos, kas izmanto līdzīgu pieeju ar sparse failiem, ir parādījusies veiktspējas kritums, kad saspiest ir ieslēgts.
Kā ieslēgt un konfigurēt
Kā jau iepriekš tika minēts, minimālā Apache Ignite versija, kas atbalsta disk page compression: 2.8 un tiek atbalstīta tikai operētājsistēmā Linux. Ieslēgšana un konfigurācija tiek veikta šādi:
- Class-path jābūt modulis ignite-compression. Noklusējuma tas atrodas Apache Ignite izplatījumā direktorijā libs/optional un netiek iekļauts class-path. Var vienkārši pārvietot direktoriju vienā līmenī augstāk libs un tad, uzsākot, izmantojot ignite.sh, tas tiks automātiski iekļauts.
- Persistence ir jābūt ieslēgtai (Ieslēdzas caur
DataRegionConfiguration.setPersistenceEnabled(true)). - Lapas izmēram jābūt lielākam par failu sistēmas bloka izmēru (to var iestatīt, izmantojot
DataStorageConfiguration.setPageSize()). - Katram kešam, kura dati ir jāsaspiest, nepieciešams konfigurācijā iestatīt saspiešanas metodi un (pēc izvēles) saspiešanas līmeni (metodes
CacheConfiguration.setDiskPageCompression(), CacheConfiguration.setDiskPageCompressionLevel()).
WAL saspiešana
Efemerāli vispārējie mākonīši
Kas ir WAL un kāpēc tas ir nepieciešams? Ļoti īsi: tas ir žurnāls, kurā tiek ierakstīti visi notikumi, kas beigu beigās maina lapu glabāšanu. To galvenokārt izmanto, lai nodrošinātu atjaunošanu gadījumā, ja notiek kļūme. Jebkura operācija pirms vadības nodošanas lietotājam vispirms jāieraksta WAL, lai, ja notiek kļūme, šos ierakstus varētu atskaņot no žurnāla un atjaunot visas operācijas, par kurām lietotājs saņēmis pozitīvu atbildi, pat ja šīs operācijas vēl nav atspoguļojušās lapu glabāšanā diskā (iepriekš jau tika aprakstīts, ka faktiskā ierakstīšana lapu glabāšanā tiek veikta procesā, ko sauc par "checkpoint" ar nelielu aizkavēšanos, ko īsteno atsevišķi pavedieni).
Ieraksti WAL tiek dalīti loģiskajos un fiziskajos. Loģiskie ieraksti ir paši atslēgas un vērtības. Fiziskie ieraksti atspoguļo izmaiņas lapās lapu glabāšanā. Ja loģiskie ieraksti var būt noderīgi arī citos gadījumos, fiziskie ieraksti ir nepieciešami tikai, lai atjaunotu datus gadījumā, ja notiek kļūme, un nepieciešami tikai ieraksti no pēdējā veiksmīgā punktā. Šeit mēs neiedziļināsimies sīkāk un nepaskaidrosim, kāpēc tas darbojas tieši tā, bet, ja kādam interesē, var atsaukties uz jau pieminēto rakstu Apache Ignite Wiki: .
Uz vienu loģisko ierakstu bieži attiecas vairāki fiziskie ieraksti. Tātad, piemēram, viena operācija put kešā ietekmē vairākas lapas lapu atmiņā (lapa ar pašiem datiem, lapas ar indeksiem, lapas ar brīvo sarakstu). Dažos sintētiskajos testos man izdevās noteikt, ka fiziskie ieraksti veidoja līdz 90% WAL faila apjoma. Turklāt tie ir nepieciešami ļoti īsu laiku (noklusējuma intervāls starp punktiem ir 3 minūtes). Būtu loģiski atbrīvoties no šiem datiem pēc to aktualitātes zaudēšanas. Tieši to īsteno WAL kompakcijas mehānisms, atbrīvoties no fiziskajiem ierakstiem un saspiest ar zip atlikušos loģiskos ierakstus, tādējādi faila izmērs tiek samazināts ļoti būtiski (dažreiz pat desmitkārtīgi).
Fiziski WAL sastāv no vairākiem segmentiem (noklusējumā 10) ar fiksētu izmēru (noklusējumā 64MB), kurus pārraksta pa apli. Kad pašreizējais segments ir piepildīts, nākamais segments tiek piešķirts pašreizējam, un piepildītais segments tiek dublēts arhīvā atsevišķā plūsmā. WAL kompakcija jau darbojas ar arhīva segmentiem. Arī atsevišķā plūsmā tā uzrauga checkpoint izpildi un sāk saspiešanu arhīva segmentiem, fiziskās ieraksti, kuriem vairs nav nepieciešami.

Ietekme uz veiktspēju
Tā kā WAL kompakcijas process darbojas atsevišķā plūsmā, tiešai ietekmei uz veicamajām darbībām nevajadzētu būt. Bet tam tomēr ir papildu fona slodze uz CPU (saspiešana) un disku (katra WAL segmenta lasīšana no arhīva un saspiešanas segmentu ierakstīšana), tāpēc, ja sistēma darbojas uz iespēju robežas, tas arī novedīs pie veiktspējas pasliktināšanās.
Kā ieslēgt un konfigurēt
Ieslēgt WAL kompakciju var, izmantojot īpašību WalCompactionEnabled par DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Arī, izmantojot metodi DataStorageConfiguration.setWalCompactionLevel(), var iestatīt saspiešanas pakāpi, ja nepietiek ar noklusējuma vērtību (BEST_SPEED).
WAL lapas attēla saspiešana
Efemerāli vispārējie mākonīši
Iepriekš jau noskaidrojām, ka WAL ieraksti tiek iedalīti loģiskajos un fiziskajos. Katras lapas katras izmaiņas lapu atmiņā veido fizisko WAL ierakstu. Fiziskie ieraksti savukārt tiek iedalīti 2 apakšveidlapās: lapas momentuzņēmuma ieraksts un delta ieraksts. Katra reize, kad mēs kaut ko mainām lapā un pārvēršam to no tīra stāvokļa netīrā, WAL saglabā pilnu šīs lapas kopiju (lapas momentuzņēmuma ieraksts — lapas snipešots). Pat ja mēs mainām tikai vienu baitu, WAL tiks saglabāts ieraksts, kura izmērs ir nedaudz lielāks par lapas izmēru. Ja mēs mainām kaut ko jau netīrā lapā, tad WAL izveidos delta ierakstu, kurā atspoguļotas tikai izmaiņas salīdzinājumā ar iepriekšējo lapas stāvokli, taču ne visa lapa kopumā. Ņemot vērā, ka lapu stāvokļa atsākšana no netīra uz tīru tiek veikta pārbaudē, tūlīt pēc pārbaudes uzsākšanas praktiski visi fiziskie ieraksti būs tikai no lapu snipešotiem (jo visas lapas tūlīt pēc pārbaudes uzsākšanas ir tīras), tad tuvojoties nākamajai pārbaudei, delta ierakstu proporcija sāk pieaugt un atkal tiek nulle uz nākamās pārbaudes sākumā. Mērījumi dažos sintētiskajos testos liecināja, ka momentuzņēmumu proporcija kopējā fizisko ierakstu apjomā sasniedz 90%.
WAL lapas momentuzņēmumu saspiešanas ideja ir saspiežot lapu momentuzņēmumus, izmantojot jau gatavu instrumentu lapu saspiešanai (skat. disk page compression). Tajā pašā laikā WAL ieraksti tiek saglabāti secīgi pievienojot tos, un nav vajadzīga ierakstu sasaistīšana ar failu sistēmas bloku robežām, tādēļ šeit, atšķirībā no disk page compression mehānisma, mums nemaz nav vajadzīgi plāni faili, attiecīgi šis mehānisms darbosies ne tikai uz Linux OS. Turklāt mums vairs nav svarīgi, cik ļoti mēs spējam saspiest lapu. Pat ja mēs atbrīvojam 1 baitu, tas jau ir pozitīvs rezultāts, un mēs varam saglabāt WAL saspiestos datus, atšķirībā no disk page compression, kur mēs saglabājam saspiesto lapu tikai tad, ja esam atbrīvojuši vairāk nekā 1 failu sistēmas bloku.
Lappuses — labi saspiežami dati, to daļa kopējā WAL apjomā ir ļoti augsta, tādējādi, nemainot WAL faila formātu, mēs varam sasniegt ievērojamu tā izmēra samazinājumu. Saspiešana, tostarp loģiskās ierakstu saspiešana, prasītu formatēšanas izmaiņas un saderības zudumu, piemēram, ārējiem patērētājiem, kuriem varētu būt interesanti loģiskie ieraksti, tajā pašā laikā nenesot ievērojamu faila apjoma samazinājumu.
Kā jau disk lapu saspiešanai, WAL lapu saspiešanai var izmantot ZSTD, LZ4, Snappy saspiešanas algoritmus, kā arī SKIP_GARBAGE režīmu.
Ietekme uz veiktspēju
Nav grūti pamanīt, ka tieša WAL lapu saspiešanas iekļaušana ietekmē tikai plūsmas, kas ieraksta datus lapu atmiņā, t.i., tās plūsmas, kas maina datus kešatmiņā. Lasīšana no WAL fiziskajiem ierakstiem notiek tikai vienu reizi, kad mezgls tiek restartēts pēc krišanas (un tikai krišanas gadījumā pārbaudes punktā).
Uz plūsmām, kas maina datus, tas ietekmē šādi: mēs iegūstam negatīvu efektu (CPU) dēļ nepieciešamības katru reizi saspiež lapu pirms ierakstīšanas diskā un pozitīvu efektu (disk IO) dēļ ievadāmo datu samazināšanās. Tātad viss ir vienkārši, ja sistēmas veiktspēja atkarīga no CPU, iegūstam nelielu pasliktināšanos, ja no diska ievades/izvades — iegūstam pieaugumu.
Netieši WAL izmēra samazināšana arī pozitīvi ietekmē plūsmas, kas arhivē WAL segmentus, un WAL saspiešanas plūsmas.
Reāli veiktspējas testi mūsu vidē, izmantojot sintētiskos datus, parādīja nelielu pieaugumu (caurlaidība pieauga par 10%-15%, latentums samazinājās par 10%-15%).
Kā ieslēgt un konfigurēt
Minimālā Apache Ignite versija: 2.8. Iekļaušana un konfigurēšana tiek veikta šādi:
- Class-path jābūt modulis ignite-compression. Noklusējuma tas atrodas Apache Ignite izplatījumā direktorijā libs/optional un netiek iekļauts class-path. Var vienkārši pārvietot direktoriju vienā līmenī augstāk libs un tad, uzsākot, izmantojot ignite.sh, tas tiks automātiski iekļauts.
- Persistence ir jābūt ieslēgtai (Ieslēdzas caur
DataRegionConfiguration.setPersistenceEnabled(true)). - Jānorāda saspiešanas režīms, izmantojot metodi
DataStorageConfiguration.setWalPageCompression(), pēc noklusējuma saspiešana ir atspējota (DISABLED režīms). - Opcionalizēti var norādīt saspiešanas pakāpi, izmantojot metodi
DataStorageConfiguration.setWalPageCompression(), pieļaujamās vērtības katram režīmam, skatiet javadoc pie metodes.
Secinājums
Apskatītie datu saspiešanas mehānismi Apache Ignite var tikt izmantoti neatkarīgi viens no otra, bet ir pieļaujamas arī jebkādas to kombinācijas. Izpratne par to darbības principiem ļaus noteikt, cik tie ir piemēroti jūsu uzdevumiem jūsu vidē un par ko būs jāupurē, tos izmantojot. Disku lapu saspiešana ir paredzēta galvenā krātuves saspiešanai un var nodrošināt vidēja līmeņa saspiešanu. WAL lapu momentuzņēmumu saspiešana sniegs vidēja līmeņa saspiešanu jau WAL failiem, un, visticamāk, pat palielinās veiktspēju. WAL kompakcija uz veiktspēju negatīvi neietekmēs, bet visvairāk samazinās WAL failu izmēru, iznīcinot fiziskās ierakstus.
Avots: habr.com
