Cumpressione di dati in Apache Ignite. L'esperienza di Sber

Cumpressione di dati in Apache Ignite. L'esperienza di SberQuandu u travagliu cù grandi volumi di dati, u prublema di a mancanza di spaziu di discu pò esse à volte. Una manera di risolve stu prublema hè a cumpressione, grazie à quale, nantu à u stessu equipamentu, pudete permette di aumentà i volumi di almacenamiento. In questu articulu, guardemu cumu funziona a compressione di dati in Apache Ignite. Questu articulu descriverà solu i metudi di cumpressione di discu implementati in u pruduttu. L'altri metudi di cumpressione di dati (nantu à a reta, in memoria), implementati o micca, restanu fora di u scopu.

Allora, cù u modu di persistenza attivatu, per via di cambiamenti di dati in i cache, Ignite cumencia à scrive à u discu:

  1. Cuntenutu di cache
  2. Write Ahead Log (in seguitu solu WAL)

Ci hè statu un mecanismu per a compressione WAL per un bellu pezzu, chjamatu cumpressione WAL. L'Apache Ignite 2.8, liberatu di pocu tempu, hà introduttu dui meccanismi più chì permettenu di cumpressione di dati nantu à u discu: compressione di pagine di discu per cumpressione di u cuntenutu di cache è compressione di snapshot di pagina WAL per cumpressione di alcune entrate WAL. Più dettagli nantu à tutti i trè di sti miccanismi sottu.

Cumpressione di a pagina di discu

Cumu serà ch'ella ùn stu travagliu

Prima, andemu à piglià un ochju assai brevi à cumu Ignite almacena i dati. A memoria di pagina hè aduprata per u almacenamentu. A dimensione di a pagina hè stabilita à l'iniziu di u node è ùn pò micca esse cambiatu in tappe successive; ancu, a dimensione di a pagina deve esse una putenza di dui è un multiplu di a dimensione di bloccu di u sistema di fugliale. E pagine sò caricate in RAM da u discu quantu necessariu; a dimensione di dati nantu à u discu pò esse più di a quantità di RAM assignata. Se ùn ci hè micca abbastanza spaziu in RAM per carricà una pagina da u discu, e pagine vechje, micca più usate seranu scacciate da a RAM.

I dati sò guardati nantu à u discu in a forma seguente: un schedariu separatu hè creatu per ogni partizione di ogni gruppu di cache; in questu schedariu, e pagine appariscenu una dopu à l'altru in ordine di indice ascendente. L'identificatore di a pagina completa cuntene l'identificatore di u gruppu di cache, u numeru di partizione è l'indici di pagina in u schedariu. Cusì, utilizendu l'identificatore di pagina completa, pudemu determinà unicu u schedariu è l'offset in u schedariu per ogni pagina. Pudete leghje più nantu à a memoria di paginazione in l'articulu Apache Ignite Wiki: Ignite Persistent Store - sottu u cappucciu.

U mecanismu di cumpressione di a pagina di discu, cum'è pudete guessà da u nome, travaglia à u livellu di a pagina. Quandu stu mecanismu hè attivatu, i dati in RAM sò processati cum'è, senza alcuna cumpressione, ma quandu e pagine sò salvate da a RAM à u discu, sò cumpressi.

Ma cumpressà ogni pagina individualmente ùn hè micca una suluzione à u prublema; avete bisognu di riduce in qualchì manera a dimensione di i fugliali di dati resultanti. Se a dimensione di a pagina ùn hè più fissata, ùn pudemu più scrive pagine à u schedariu una dopu à l'altru, postu chì questu pò creà una quantità di prublemi:

  • Utilizendu l'indici di a pagina, ùn pudemu micca calculà l'offset da quale si trova in u schedariu.
  • Ùn hè micca chjaru chì fà cù e pagine chì ùn sò micca à a fine di u schedariu è cambianu a so dimensione. Se a dimensione di a pagina diminuite, u spaziu liberatu sparisce. Se a dimensione di a pagina aumenta, avete bisognu di circà un novu postu in u schedariu per questu.
  • Se una pagina si move da una quantità di byte chì ùn hè micca un multiplu di a dimensione di u bloccu di u sistema di fugliale, allora a lettura o a scrittura serà bisognu di toccu un bloccu di u sistema di file, chì pò purtà à a degradazione di u rendiment.

Per evitari di risolve questi prublemi à u so propiu livellu, a compressione di pagine di discu in Apache Ignite usa un mecanismu di sistema di fugliale chjamatu sparse files. Un schedariu sparse hè quellu in quale alcune regioni zero-piene ponu esse marcate cum'è "buchi". In questu casu, nisun bloccu di u sistema di fugliale ùn serà attribuitu per almacenà questi buchi, risultatu in un risparmiu di spaziu di discu.

Hè logicu chì per liberà un bloccu di u sistema di fugliale, a dimensione di u pirtusu deve esse più grande o uguale à u bloccu di u sistema di fugliale, chì impone una limitazione supplementaria à a dimensione di a pagina è Apache Ignite: per a compressione per avè qualchì effettu, a dimensione di a pagina deve esse strettamente più grande di a dimensione di u bloccu di u sistema di fugliale. Se a dimensione di a pagina hè uguale à a dimensione di u bloccu, allora ùn pudemu mai liberà un bloccu unicu, postu chì per liberà un bloccu unicu, a pagina cumpressa deve occupà 0 bytes. Se a dimensione di a pagina hè uguale à a dimensione di 2 o 4 blocchi, pudemu digià liberà almenu un bloccu se a nostra pagina hè cumpressa à almenu 50% o 75%, rispettivamente.

Cusì, a descrizzione finale di u funziunamentu di u mecanismu: Quandu scrivite una pagina à u discu, un tentativu hè fattu per cumpressà a pagina. Se a dimensione di a pagina cumpressa permette di liberà unu o più blocchi di sistema di fugliale, allora a pagina hè scritta in forma compressa, è un "bucu" hè fattu in u locu di i blocchi liberati (una chjama di u sistema hè eseguita). fallocate() cù a bandiera di punch hole). Se a dimensione di a pagina cumpressata ùn permette micca di liberà i blocchi, a pagina hè salvata cum'è, senza cumpressione. Tutti l'offsets di pagina sò calculati cum'è senza cumpressione, multiplicendu l'indici di pagina per a dimensione di a pagina. Nisuna trasferimentu di pagine hè necessariu per sè stessu. L'offsets di pagina, cum'è senza cumpressione, cascanu nantu à i cunfini di i blocchi di u sistema di fugliale.

Cumpressione di dati in Apache Ignite. L'esperienza di Sber

In l'implementazione attuale, Ignite pò travaglià solu cù fugliali sparsi sottu Linux OS; per quessa, a cumpressione di pagine di discu pò esse attivata solu quandu si usa Ignite in stu sistema operatore.

Algoritmi di cumpressione chì ponu esse utilizati per a compressione di pagine di discu: ZSTD, LZ4, Snappy. Inoltre, ci hè un modu di uperazione (SKIP_GARBAGE), in quale solu u spaziu inutilizatu in a pagina hè ghjittatu fora senza applicà cumpressione nantu à i dati restante, chì reduce a carica nantu à u CPU cumparatu cù l'algoritmi listati prima.

Impattu di rendiment

Sfurtunatamente, ùn aghju micca realizatu misurazioni di rendiment reali nantu à stands veri, postu chì ùn avemu micca pensatu à utilizà stu mecanismu in a produzzione, ma pudemu speculate in teoria induve perdemu è induve vinceremu.

Per fà questu, avemu bisognu di ricurdà cumu e pagine sò leghjite è scritte quandu si accede:

  • Quandu eseguite una operazione di lettura, hè prima cercata in RAM; se a ricerca ùn hè micca successu, a pagina hè caricata in RAM da u discu da u stessu filu chì esegue a lettura.
  • Quandu una operazione di scrittura hè realizata, a pagina in RAM hè marcata cum'è brutta, ma a pagina ùn hè micca salvata fisicamente à u discu immediatamente da u filu chì esegue a scrittura. Tutte e pagine brutte sò salvate à u discu dopu in u prucessu di checkpoint in fili separati.

Allora l'impattu nantu à l'operazioni di lettura hè:

  • Pusitivu (discu IO), per via di una diminuzione di u numeru di blocchi di sistema di fugliale di lettura.
  • Negativu (CPU), per via di a carica supplementaria necessaria da u sistema operatore per travaglià cù schedarii sparse. Hè ancu pussibule chì l'operazioni IO supplementari appariscenu implicitamente quì per salvà una struttura di file sparse più cumplessa (sfurtunatamente, ùn sò micca familiarizatu cù tutti i dettagli di cumu funziona i schedari sparse).
  • Negativu (CPU), per via di a necessità di decompressà e pagine.
  • Ùn ci hè micca impattu annantu à l'operazione di scrittura.
  • Impattu nantu à u prucessu di checkpoint (tuttu quì hè simile à l'operazioni di lettura):
  • Pusitivu (discu IO), per via di una diminuzione di u numeru di blocchi di sistema di schedari scritti.
  • Negativu (CPU, possibbilmente IO di discu), per via di travaglià cù schedari sparse.
  • Negativu (CPU), per via di a necessità di cumpressione di pagina.

Chì latu di a scala inclinarà a scala? Questu tuttu dipende assai di l'ambiente, ma sò inclinatu à crede chì a compressione di pagine di discu prubabilmente porta à a degradazione di u rendiment in a maiò parte di i sistemi. Inoltre, e teste nantu à altri DBMS chì utilizanu un approcciu simili cù i fugliali sparsi mostranu una calata di rendiment quandu a compressione hè attivata.

Cumu attivà è cunfigurà

Cumu l'esitatu sopra, a versione minima di Apache Ignite chì sustene a compressione di pagine di discu hè 2.8 è solu u sistema operatore Linux hè supportatu. Habilita è cunfigurà cusì:

  • Ci deve esse un modulu ignite-compressione in u class-path. Per automaticamente, si trova in a distribuzione Apache Ignite in u repertoriu libs / optional è ùn hè micca inclusu in a class-path. Pudete simpricimenti spustà u repertoriu à un livellu à libbres è dopu, quandu u eseguite attraversu ignite.sh, serà attivatu automaticamente.
  • A persistenza deve esse attivata (Abilitatu via DataRegionConfiguration.setPersistenceEnabled(true)).
  • A dimensione di a pagina deve esse più grande ch'è a dimensione di u bloccu di u sistema di fugliale (pudete stabilisce aduprendu DataStorageConfiguration.setPageSize() ).
  • Per ogni cache chì a so dati deve esse cumpressu, duvete cunfigurà u metudu di cumpressione è (opcionalmente) u livellu di compressione (metudi). CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

Compactazione WAL

Cumu serà ch'ella ùn stu travagliu

Cosa hè WAL è perchè hè necessariu? Moltu brevemente: questu hè un logu chì cuntene tutti l'avvenimenti chì ultimamente cambianu l'almacenamiento di a pagina. Hè necessariu principarmenti per pudè ritruvà in casu di caduta. Ogni operazione, prima di dà u cuntrollu à l'utilizatore, deve prima registrà un avvenimentu in WAL, perchè in casu di fallimentu, pò esse ghjucatu in u logu è restituite tutte e operazioni per quale l'utilizatore hà ricevutu una risposta riescita, ancu s'è queste operazioni. ùn hà micca avutu u tempu per esse riflessu in l'almacenamiento di a pagina nantu à u discu (dighjà sopra Hè statu descrittu chì a scrittura attuale à a tenda di a pagina hè fatta in un prucessu chjamatu "checkpointing" cù qualchì ritardu per fili separati).

L'entrata in WAL sò divise in logica è fisica. I booleani sò i chjavi è i valori stessi. Fisica - riflette i cambiamenti à e pagine in u magazinu di pagine. Mentre i registri lògichi ponu esse utili per certi altri casi, i registri fisichi sò necessarii solu per a ricuperazione in casu di un crash è i registri sò necessarii solu da l'ultimu puntu di cuntrollu successu. Quì ùn andemu micca in dettagliu è spieghemu perchè funziona cusì, ma quelli chì sò interessati ponu riferite à l'articulu digià citatu nantu à l'Apache Ignite Wiki: Ignite Persistent Store - sottu u cappucciu.

Ci sò spessu parechji registri fisichi per record logicu. Hè, per esempiu, una operazione di mette in u cache affetta parechje pagine in a memoria di pagina (una pagina cù e dati stessu, pagine cù indici, pagine cù listi liberi). In certi testi sintetici, aghju trovu chì i registri fisichi occupanu finu à u 90% di u schedariu WAL. In ogni casu, sò necessarii per un pocu tempu (per automaticamente, l'intervallu trà i punti di cuntrollu hè di 3 minuti). Saria logica à ridivà di sta dati dopu à perde a so rilevanza. Questu hè esattamente ciò chì face u mecanismu di compactazione WAL: si sbarazza di i registri fisici è comprime i registri logichi rimanenti cù zip, mentre chì a dimensione di u schedariu hè ridutta assai significativamente (a volte di decine di volte).

Fisicamente, WAL hè custituitu da parechji segmenti (10 per difettu) di una dimensione fissa (64MB per difettu), chì sò soprascritti in una manera circular. Appena u segmentu attuale hè cumpletu, u segmentu prossimu hè assignatu cum'è attuale, è u segmentu pienu hè copiatu à l'archiviu da un filu separatu. A compactazione WAL travaglia digià cù segmenti d'archivi. Inoltre, cum'è un filu separatu, monitoreghja l'esekzione di u puntu di cuntrollu è principia a compressione in segmenti d'archivi per i quali i registri fisichi ùn sò più necessarii.

Cumpressione di dati in Apache Ignite. L'esperienza di Sber

Impattu di rendiment

Siccomu a compattazione WAL funziona cum'è un filu separatu, ùn deve esse micca impattu direttu nantu à l'operazioni esse realizatu. Ma ancu mette una carica di fondo supplementu nantu à u CPU (compressione) è u discu (leghjendu ogni segmentu WAL da l'archiviu è scrivite i segmenti compressi), perchè se u sistema funziona à a so capacità massima, ancu porta à a degradazione di u rendiment.

Cumu attivà è cunfigurà

Pudete attivà a compattazione WAL usendu a pruprietà WalCompactionEnabled в DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Inoltre, utilizendu u metudu DataStorageConfiguration.setWalCompactionLevel(), pudete stabilisce u nivellu di cumpressione si ùn site micca cuntentu cù u valore predeterminatu (BEST_SPEED).

Cumpressione di snapshot di pagina WAL

Cumu serà ch'ella ùn stu travagliu

Avemu digià scupertu chì in i registri WAL sò spartuti in lògichi è fisichi. Per ogni cambiamentu di ogni pagina, un record WAL fisicu hè generatu in a memoria di pagina. I registri fisichi, à u turnu, sò ancu divisi in 2 sottotipi: registru di snapshot di pagina è registru delta. Ogni volta chì cambiamu qualcosa in una pagina è u trasfiriu da un statu pulitu à un statu bruttu, una copia cumpleta di sta pagina hè guardata in WAL (registru di snapshot di pagina). Ancu s'è avemu cambiatu solu un byte in WAL, u record serà un pocu più grande di a dimensione di a pagina. Se cambiamu qualcosa nantu à una pagina digià brutta, un registru delta hè furmatu in WAL, chì riflette solu cambiamenti cumparatu cù u statu precedente di a pagina, ma micca tutta a pagina. Siccomu resetting the state of pages from dirty to clean is performed during the checkpoint process, subitu dopu à l'iniziu di u checkpoint, quasi tutti i registri fisichi sò custituiti solu di snapshots di pagine (perchè tutte e pagine immediatamente dopu à l'iniziu di u checkpoint sò pulite) , dopu chì avvicinemu à u prossimu puntu di cuntrollu, a frazione di record di delta cumencia à cresce è resettate novu à u principiu di u prossimu puntu di cuntrollu. E misurazioni in certi testi sintetici anu dimustratu chì a parte di snapshots di pagina in u voluminu tutale di registri fisichi righjunghji u 90%.

L'idea di cumpressione di snapshot di pagina WAL hè di cumpressà snapshots di pagina utilizendu un strumentu di compressione di pagina pronta (vede a compressione di pagina di discu). À u listessu tempu, in WAL, i registri sò salvati in modu sequenziale in modu append-only è ùn ci hè bisognu di ligà i registri à i limiti di i blocchi di u sistema di fugliale, cusì quì, à u cuntrariu di u mecanismu di compressione di pagine di discu, ùn avemu micca bisognu di schedari sparse à tuttu; dunque, stu mecanismu ùn funziona micca solu in u SO Linux. Inoltre, ùn ci importa più quantu pudemu cumpressà a pagina. Ancu s'è avemu liberatu 1 byte, questu hè digià un risultatu pusitivu è pudemu salvà dati cumpressi in WAL, à u cuntrariu di a compressione di a pagina di discu, induve salvemu a pagina cumpressata solu s'è avemu liberatu più di 1 bloccu di sistema di schedari.

E pagine sò dati assai cumpressibili, a so parte in u voluminu WAL tutale hè assai altu, cusì senza cambià u furmatu di u schedariu WAL pudemu avè una riduzione significativa di a so dimensione. A cumpressione, cumpresi i registri lògichi, avaristi bisognu di un cambiamentu di formatu è a perdita di cumpatibilità, per esempiu, per i cunsumatori esterni chì ponu esse interessate in i registri lògichi, ma ùn portanu micca à una riduzione significativa di a dimensione di u schedariu.

Cum'è cù a compressione di pagine di discu, a compressione di snapshot di pagina WAL pò utilizà l'algoritmi di compressione ZSTD, LZ4, Snappy, è ancu u modu SKIP_GARBAGE.

Impattu di rendiment

Ùn hè micca difficiule di nutà chì l'attivazione diretta di a compressione di snapshot di pagina WAL affetta solu i fili chì scrivenu dati à a memoria di pagina, vale à dì quelli fili chì cambianu dati in cache. A lettura di i registri fisichi da WAL si faci una sola volta, à u mumentu chì u node hè risuscitatu dopu à una caduta (è solu s'ellu casca durante un puntu di cuntrollu).

Questu affetta i fili chì cambianu i dati in a seguente manera: avemu un effettu negativu (CPU) per a necessità di cumpressà a pagina ogni volta prima di scrive à u discu, è un effettu pusitivu (discu IO) per una riduzzione in a quantità di dati scritti. Per quessa, tuttu hè simplice quì: se u rendiment di u sistema hè limitatu da u CPU, avemu una ligera degradazione, se hè limitata da l'I / O di u discu, avemu un aumentu.

Indirettamenti, a riduzione di a dimensione WAL affetta ancu (pusitivu) i flussi chì scaricanu i segmenti WAL in l'archiviu è i flussi di compactazione WAL.

I testi di rendiment reali in u nostru ambiente cù dati sintetici anu dimustratu un ligeru aumentu (a produzzione aumentata da 10% -15%, a latenza diminuite da 10% -15%).

Cumu attivà è cunfigurà

Versione minima di Apache Ignite: 2.8. Habilita è cunfigurà cusì:

  • Ci deve esse un modulu ignite-compressione in u class-path. Per automaticamente, si trova in a distribuzione Apache Ignite in u repertoriu libs / optional è ùn hè micca inclusu in a class-path. Pudete simpricimenti spustà u repertoriu à un livellu à libbres è dopu, quandu u eseguite attraversu ignite.sh, serà attivatu automaticamente.
  • A persistenza deve esse attivata (Abilitatu via DataRegionConfiguration.setPersistenceEnabled(true)).
  • U modu di cumpressione deve esse stabilitu cù u metudu DataStorageConfiguration.setWalPageCompression(), a compressione hè disattivata per difettu (modu DISABLED).
  • Opcionalmente, pudete stabilisce u livellu di cumpressione cù u metudu DataStorageConfiguration.setWalPageCompression(), vede u javadoc per u metudu per i valori validi per ogni modu.

cunchiusioni

I miccanismi di cumpressione di dati cunsiderati in Apache Ignite ponu esse utilizati indipindentamente l'un l'altru, ma ogni cumminazzioni di elli hè ancu accettabile. A capiscenu cumu travaglianu vi permetterà di determinà quantu sò adattati per i vostri compiti in u vostru ambiente è ciò chì duverete sacrificà quandu l'utilizanu. A compressione di a pagina di discu hè pensata per cumpressà l'almacenamiento principale è pò dà un rapportu di compressione mediu. A compressione di snapshot di pagina WAL darà un gradu mediu di compressione per i schedari WAL, è probabilmente ancu migliurà u rendiment. A compattazione WAL ùn hà micca un effettu pusitivu nantu à u rendiment, ma riducerà a dimensione di i schedari WAL quant'è pussibule eliminendu i registri fisichi.

Source: www.habr.com

Add a comment