Datumpremado en Apache Ignite. La sperto de Sber

Datumpremado en Apache Ignite. La sperto de SberKiam vi laboras kun grandaj volumoj de datumoj, foje povas aperi la problemo de manko de diskspaco. Unu maniero solvi ĉi tiun problemon estas kunpremado, danke al kiu, sur la sama ekipaĵo, vi povas pagi pliigi stokajn volumojn. En ĉi tiu artikolo, ni rigardos kiel datumkunpremado funkcias en Apache Ignite. Ĉi tiu artikolo priskribos nur la diskkunpremajn metodojn efektivigitajn ene de la produkto. Aliaj metodoj de datumkunpremo (tra la reto, en memoro), ĉu efektivigitaj aŭ ne, restos ekster la amplekso.

Do, kun persista reĝimo ebligita, kiel rezulto de ŝanĝoj en datumoj en la kaŝmemoroj, Ignite komencas skribi al disko:

  1. Enhavo de kaŝmemoroj
  2. Skribu Antaŭen Protokolo (ĉi-poste simple WAL)

Ekzistas mekanismo por WAL-kunpremado de sufiĉe tempo nun, nomita WAL-kunpremado. La lastatempe eldonita Apache Ignite 2.8 enkondukis du pliajn mekanismojn, kiuj ebligas vin kunpremi datumojn sur disko: disko-paĝa kunpremado por kunpremi la enhavon de kaŝmemoroj kaj WAL-paĝa momentfoto-kunpremado por kunpremi kelkajn WAL-enskribojn. Pli da detaloj pri ĉiuj tri el ĉi tiuj mekanismoj malsupre.

Diskopaĝa kunpremo

Kiel tio funkcias

Unue, ni rigardu tre mallongan kiel Ignite konservas datumojn. Paĝmemoro estas uzata por stokado. La paĝgrandeco estas metita ĉe la komenco de la nodo kaj ne povas esti ŝanĝita en pli postaj stadioj; ankaŭ, la paĝgrandeco devas esti potenco de du kaj oblo de la dosiersistema blokgrandeco. Paĝoj estas ŝarĝitaj en RAM de disko laŭbezone; la grandeco de datumoj sur disko povas superi la kvanton de asignita RAM. Se ne estas sufiĉe da spaco en RAM por ŝargi paĝon el disko, malnovaj, ne plu uzataj paĝoj estos forigitaj el RAM.

La datumoj estas konservitaj sur disko en la jena formo: aparta dosiero estas kreita por ĉiu sekcio de ĉiu kaŝmemorgrupo; en ĉi tiu dosiero, paĝoj aperas unu post la alia en supreniranta indeksa sinsekvo. La plena paĝa identigilo enhavas la kaŝmemorgrupidentigilon, sekcionumeron kaj paĝan indekson en la dosiero. Tiel, uzante la plenan paĝan identigilon, ni povas unike determini la dosieron kaj la ofseton en la dosiero por ĉiu paĝo. Vi povas legi pli pri paĝmemoro en la Apache Ignite Wiki-artikolo: Ignite Persistent Store - sub la kapuĉo.

La diskpaĝa kunprema mekanismo, kiel vi povas supozi laŭ la nomo, funkcias ĉe la paĝa nivelo. Kiam ĉi tiu mekanismo estas ebligita, datumoj en RAM estas prilaboritaj kiel estas, sen ajna kunpremo, sed kiam paĝoj estas konservitaj de RAM al disko, ili estas kunpremitaj.

Sed kunpremi ĉiun paĝon individue ne estas solvo al la problemo; vi devas iel redukti la grandecon de la rezultaj datumdosieroj. Se la paĝa grandeco ne plu estas fiksita, ni ne plu povas skribi paĝojn al la dosiero unu post alia, ĉar tio povas krei kelkajn problemojn:

  • Uzante la paĝan indekson, ni ne povos kalkuli la ofseton per kiu ĝi troviĝas en la dosiero.
  • Ne estas klare, kion fari kun paĝoj kiuj ne estas ĉe la fino de la dosiero kaj ŝanĝas ilian grandecon. Se la paĝa grandeco malpliiĝas, la spaco, kiun ĝi liberigis, malaperas. Se la paĝa grandeco pliiĝas, vi devas serĉi novan lokon en la dosiero por ĝi.
  • Se paĝo moviĝas je kelkaj bajtoj kiuj ne estas oblo de la dosiersistema blokgrandeco, tiam legi aŭ skribi ĝin postulos tuŝi unu plian dosiersistemblokon, kio povas konduki al rendimento degenero.

Por eviti solvi ĉi tiujn problemojn je sia propra nivelo, diskpaĝa kunpremo en Apache Ignite uzas dosiersisteman mekanismon nomatan maldensaj dosieroj. Maldensa dosiero estas tiu en kiu kelkaj nul-plenaj regionoj povas esti markitaj kiel "truoj". En ĉi tiu kazo, neniuj dosiersistemaj blokoj estos asignitaj por stoki ĉi tiujn truojn, rezultigante ŝparojn sur diskspaco.

Estas logike, ke por liberigi dosiersistemblokon, la grandeco de la truo devas esti pli granda ol aŭ egala al la dosiersistembloko, kiu trudas aldonan limigon al la paĝgrandeco kaj Apache Ignite: por kunpremado havi ajnan efikon, la paĝa grandeco devas esti strikte pli granda ol la grandeco de la dosiersistema bloko. Se la grandeco de la paĝo egalas al la grandeco de la bloko, tiam ni neniam povos liberigi ununuran blokon, ĉar por liberigi ununuran blokon, la kunpremita paĝo devas okupi 0 bajtojn. Se la grandeco de la paĝo egalas al la grandeco de 2 aŭ 4 blokoj, ni jam povos liberigi almenaŭ unu blokon, se nia paĝo estas kunpremita al almenaŭ 50% aŭ 75% respektive.

Tiel, la fina priskribo de kiel la mekanismo funkcias: Kiam oni skribas paĝon al disko, oni provas kunpremi la paĝon. Se la grandeco de la kunpremita paĝo permesas liberigi unu aŭ pluraj dosiersistemblokojn, tiam la paĝo estas skribita en kunpremita formo, kaj "truo" estas farita anstataŭ la liberigitaj blokoj (sistemvoko estas efektivigita fallocate() kun la flago de truo). Se la grandeco de la kunpremita paĝo ne permesas liberigi la blokojn, la paĝo estas konservita tia, nekunpremita. Ĉiuj paĝaj ofsetoj estas kalkulitaj same kiel sen kunpremado, multiplikante la paĝan indekson per la paĝa grandeco. Neniu translokigo de paĝoj estas postulata memstare. Paĝaj ofsetoj, same kiel sen kunpremado, falas sur la limoj de dosiersistemaj blokoj.

Datumpremado en Apache Ignite. La sperto de Sber

En la nuna efektivigo, Ignite povas funkcii nur kun malabundaj dosieroj sub Linukso OS; sekve, diskpaĝa kunpremado nur povas esti ebligita kiam vi uzas Ignite sur ĉi tiu operaciumo.

Kunpremado-algoritmoj uzeblaj por diskpaĝa kunpremo: ZSTD, LZ4, Snappy. Krome, ekzistas operacia reĝimo (SKIP_GARBAGE), en kiu nur neuzata spaco en la paĝo estas forĵetita sen apliki kunpremadon sur la ceteraj datumoj, kiu reduktas la ŝarĝon sur la CPU kompare kun la antaŭe listigitaj algoritmoj.

Efikeco Efiko

Bedaŭrinde, mi ne faris realajn rendimentajn mezuradojn sur realaj standoj, ĉar ni ne planas uzi ĉi tiun mekanismon en produktado, sed ni povas teorie konjekti kie ni perdos kaj kie ni gajnos.

Por fari tion, ni devas memori kiel paĝoj estas legitaj kaj skribitaj kiam aliritaj:

  • Dum legado, ĝi unue estas serĉita en RAM; se la serĉo estas malsukcesa, la paĝo estas ŝarĝita en RAM de disko per la sama fadeno kiu elfaras la legadon.
  • Kiam skriba operacio estas farita, la paĝo en RAM estas markita kiel malpura, sed la paĝo ne estas fizike konservita al disko tuj per la fadeno elfaranta la skribadon. Ĉiuj malpuraj paĝoj estas konservitaj al disko poste en la kontrolpunktoprocezo en apartaj fadenoj.

Do la efiko al legaj operacioj estas:

  • Pozitiva (disko IO), pro malkresko de la nombro de legitaj dosiersistemo-blokoj.
  • Negativa (CPU), pro la aldona ŝarĝo postulata de la operaciumo por labori kun maldensaj dosieroj. Eblas ankaŭ, ke aldonaj IO-operacioj implicite aperos ĉi tie por konservi pli kompleksan maldensan dosierstrukturon (bedaŭrinde, mi ne konas ĉiujn detalojn pri kiel maldensaj dosieroj funkcias).
  • Negativa (CPU), pro la bezono malkunpremi paĝojn.
  • Ne estas efiko al skribaj operacioj.
  • Efiko al la transirejo (ĉi tie ĉio similas al legado de operacioj):
  • Pozitiva (disko IO), pro malkresko de la nombro da skribaj dosiersistemoblokoj.
  • Negativa (CPU, eble disko IO), pro laborado kun maldensaj dosieroj.
  • Negativa (CPU), pro la bezono de paĝa kunpremo.

Kiu flanko de la pesilo renversos la pesilon? Ĉio ĉio dependas de la medio, sed mi emas kredi, ke diskpaĝa kunpremado plej verŝajne kondukos al rendimento-malboniĝo ĉe plej multaj sistemoj. Plie, testoj pri aliaj DBMS, kiuj uzas similan aliron kun maldensaj dosieroj, montras malpliiĝon de rendimento kiam kunpremado estas ebligita.

Kiel ebligi kaj agordi

Kiel menciite supre, la minimuma versio de Apache Ignite kiu subtenas diskpaĝan kunpremadon estas 2.8 kaj nur la Linukso operaciumo estas subtenata. Ebligu kaj agordu jene:

  • Devas ekzisti ŝaltilo-kunprema modulo en la klasvojo. Defaŭlte, ĝi troviĝas en la distribuo Apache Ignite en la libs/laŭvola dosierujo kaj ne estas inkluzivita en la klasvojo. Vi povas simple movi la dosierujon supren unu nivelon al libs kaj tiam kiam vi rulos ĝin tra ignite.sh ĝi estos aŭtomate ebligita.
  • Persisto devas esti ebligita (Ebligita per DataRegionConfiguration.setPersistenceEnabled(true)).
  • La paĝa grandeco devas esti pli granda ol la dosiersistema blokgrandeco (vi povas agordi ĝin uzante DataStorageConfiguration.setPageSize() ).
  • Por ĉiu kaŝmemoro, kies datumoj devas esti kunpremitaj, vi devas agordi la kunpreman metodon kaj (laŭvole) la kunpreman nivelon (metodoj CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

WAL kompaktado

Kiel tio funkcias

Kio estas WAL kaj kial ĝi bezonas? Tre mallonge: ĉi tio estas protokolo, kiu enhavas ĉiujn eventojn, kiuj finfine ŝanĝas la paĝan konservadon. Ĝi necesas ĉefe por povi resaniĝi en kazo de falo. Ajna operacio, antaŭ ol doni kontrolon al la uzanto, unue devas registri eventon en WAL, tiel ke en kazo de malsukceso, ĝi povas esti reludata en la protokolo kaj restarigi ĉiujn operaciojn por kiuj la uzanto ricevis sukcesan respondon, eĉ se ĉi tiuj operacioj. ne havis tempon por esti reflektita en la paĝstokado sur disko (jam supre Oni priskribis, ke la efektiva skribo al la paĝa vendejo estas farita en procezo nomata "kontrolpunkto" kun iom da prokrasto per apartaj fadenoj).

Enskriboj en WAL estas dividitaj en logikaj kaj fizikaj. Buleaj estas la ŝlosiloj kaj valoroj mem. Fizika - reflektas ŝanĝojn al paĝoj en la paĝa vendejo. Dum logikaj rekordoj povas esti utilaj por iuj aliaj kazoj, fizikaj rekordoj estas necesaj nur por reakiro en kazo de kraŝo kaj rekordoj estas necesaj nur ekde la lasta sukcesa transirejo. Ĉi tie ni ne eniros en detalojn kaj klarigos kial ĝi funkcias tiel, sed interesiĝantoj povas raporti al la jam menciita artikolo en la Apache Ignite Vikio: Ignite Persistent Store - sub la kapuĉo.

Ofte ekzistas pluraj fizikaj rekordoj per logika rekordo. Tio estas, ekzemple, unu metita operacio en la kaŝmemoron influas plurajn paĝojn en paĝmemoro (paĝo kun la datumoj mem, paĝoj kun indeksoj, paĝoj kun libera-listoj). En iuj sintezaj testoj, mi trovis, ke fizikaj registroj okupis ĝis 90% de la WAL-dosiero. Tamen, ili estas bezonataj por tre mallonga tempo (defaŭlte, la intervalo inter kontrolpunktoj estas 3 minutoj). Estus logike forigi ĉi tiujn datumojn post perdo de ĝia graveco. Ĝuste tion faras la kompakta mekanismo WAL: ĝi forigas fizikajn rekordojn kaj kunpremas la ceterajn logikajn rekordojn per zip, dum la dosiergrandeco estas reduktita tre signife (foje je dekoj da fojoj).

Fizike, WAL konsistas el pluraj segmentoj (10 defaŭlte) de fiksa grandeco (64MB defaŭlte), kiuj estas anstataŭitaj en cirkla maniero. Tuj kiam la nuna segmento estas plenigita, la sekva segmento estas asignita kiel aktuala, kaj la plenigita segmento estas kopiita al la arkivo per aparta fadeno. WAL-kompaktado jam funkcias kun arkivaj segmentoj. Ankaŭ, kiel aparta fadeno, ĝi kontrolas la ekzekuton de la transirejo kaj komencas kunpremadon en arkivaj segmentoj por kiuj fizikaj rekordoj ne plu bezonas.

Datumpremado en Apache Ignite. La sperto de Sber

Efikeco Efiko

Ĉar WAL-kompaktado funkcias kiel aparta fadeno, devus esti neniu rekta efiko al la operacioj estantaj faritaj. Sed ĝi ankoraŭ metas plian fonŝarĝon sur la CPU (kunpremo) kaj disko (legante ĉiun WAL-segmenton el la arkivo kaj skribante la kunpremitajn segmentojn), do se la sistemo funkcias ĉe sia maksimuma kapacito, ĝi ankaŭ kondukos al rendimento-degenero.

Kiel ebligi kaj agordi

Vi povas ebligi WAL-kompakton uzante la posedaĵon WalCompactionEnabled в DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Ankaŭ, uzante la metodon DataStorageConfiguration.setWalCompactionLevel(), vi povas agordi la kunpreman nivelon se vi ne kontentas pri la defaŭlta valoro (BEST_SPEED).

WAL-paĝa momentprempremo

Kiel tio funkcias

Ni jam eksciis, ke en WAL rekordoj estas dividitaj en logikaj kaj fizikaj. Por ĉiu ŝanĝo al ĉiu paĝo, fizika WAL-rekordo estas generita en paĝmemoro. Fizikaj registroj, siavice, ankaŭ estas dividitaj en 2 subtipojn: paĝa momentrekordo kaj delta rekordo. Ĉiufoje kiam ni ŝanĝas ion sur paĝo kaj transdonas ĝin de pura stato al malpura stato, kompleta kopio de ĉi tiu paĝo estas konservita en WAL (paĝa momentrekordo). Eĉ se ni ŝanĝis nur unu bajton en WAL, la registro estos iomete pli granda ol la paĝa grandeco. Se ni ŝanĝas ion sur jam malpura paĝo, delta rekordo estas formita en WAL, kiu reflektas nur ŝanĝojn kompare kun la antaŭa stato de la paĝo, sed ne la tutan paĝon. Ĉar restarigi la staton de paĝoj de malpura al pura estas farita dum la transirejo, tuj post la komenco de la transirejo, preskaŭ ĉiuj fizikaj rekordoj konsistos nur el momentfotoj de paĝoj (ĉar ĉiuj paĝoj tuj post la komenco de la transirejo estas puraj) , tiam kiam ni alproksimiĝas al la sekva transirejo, la delta rekorda frakcio komencas kreski kaj restarigi denove komence de la sekva transirejo. Mezuradoj en iuj sintezaj testoj montris, ke la parto de paĝaj momentfotoj en la totala volumo de fizikaj rekordoj atingas 90%.

La ideo de WAL-paĝa kunpremado estas kunpremi paĝajn momentfotojn uzante pretan paĝan kunpremadon (vidu diskon-paĝan kunpremadon). Samtempe, en WAL, rekordoj estas konservataj sinsekve en nur aldona reĝimo kaj ne necesas ligi rekordojn al la limoj de dosiersistemaj blokoj, do ĉi tie, male al la mekanismo de kunpremado de disko-paĝo, ni ne bezonas maldensajn dosierojn ĉe ĉiuj; sekve, ĉi tiu mekanismo funkcios ne nur en la OS Linukso. Krome, por ni ne plu gravas kiom ni povis kunpremi la paĝon. Eĉ se ni liberigis 1 bajton, ĉi tio jam estas pozitiva rezulto kaj ni povas konservi kunpremitajn datumojn en WAL, male al diskpaĝa kunpremo, kie ni konservas la kunpremitan paĝon nur se ni liberigis pli ol 1 dosiersistemon.

Paĝoj estas tre kunpremeblaj datumoj, ilia parto en la totala WAL-volumo estas tre alta, do sen ŝanĝi la WAL-dosierformaton ni povas akiri signifan redukton de ĝia grandeco. Kunpremado, inkluzive de logikaj rekordoj, postulus ŝanĝon en formato kaj perdon de kongruo, ekzemple, por eksteraj konsumantoj kiuj povas interesiĝi pri logikaj rekordoj, sed ne kondukus al signifa redukto en dosiergrandeco.

Kiel ĉe disko-paĝa kunpremado, WAL-paĝa momentprempremo povas uzi ZSTD, LZ4, Snappy-kunpremad-algoritmojn, same kiel la SKIP_GARBAGE-reĝimon.

Efikeco Efiko

Ne malfacilas rimarki, ke rekte ebligi WAL-paĝan momentfoton-kunpremadon nur influas fadenojn kiuj skribas datumojn al paĝmemoro, tio estas, tiujn fadenojn kiuj ŝanĝas datumojn en kaŝmemoroj. Legado de fizikaj rekordoj de WAL okazas nur unufoje, en la momento la nodo estas levita post falo (kaj nur se ĝi falas dum transirejo).

Ĉi tio influas fadenojn kiuj ŝanĝas datumojn jene: ni ricevas negativan efikon (CPU) pro la bezono kunpremi la paĝon ĉiufoje antaŭ skribi al disko, kaj pozitivan efikon (disko IO) pro redukto de la kvanto de datumoj skribitaj. Sekve, ĉio estas simpla ĉi tie: se la sistema rendimento estas limigita de la CPU, ni ricevas iomete degeneron, se ĝi estas limigita de disko I/O, ni ricevas pliiĝon.

Nerekte, redukti la grandecon de WAL ankaŭ influas (pozitive) riveretojn kiuj forĵetas WAL-segmentojn en la arkivon kaj WAL-kompaktajn riveretojn.

Realaj agado-testoj en nia medio uzante sintezajn datumojn montris etan pliiĝon (trafluo pliiĝis je 10%-15%, latenteco malpliiĝis je 10%-15%).

Kiel ebligi kaj agordi

Minimuma Apache Ignite-versio: 2.8. Ebligu kaj agordu jene:

  • Devas ekzisti ŝaltilo-kunprema modulo en la klasvojo. Defaŭlte, ĝi troviĝas en la distribuo Apache Ignite en la libs/laŭvola dosierujo kaj ne estas inkluzivita en la klasvojo. Vi povas simple movi la dosierujon supren unu nivelon al libs kaj tiam kiam vi rulos ĝin tra ignite.sh ĝi estos aŭtomate ebligita.
  • Persisto devas esti ebligita (Ebligita per DataRegionConfiguration.setPersistenceEnabled(true)).
  • La kunprema reĝimo devas esti agordita per la metodo DataStorageConfiguration.setWalPageCompression(), kunpremado estas malebligita defaŭlte (MABILITA reĝimo).
  • Laŭvole, vi povas agordi la kunpreman nivelon uzante la metodon DataStorageConfiguration.setWalPageCompression(), vidu la javadoc por la metodo por validaj valoroj por ĉiu reĝimo.

konkludo

La konsiderataj datumpremaj mekanismoj en Apache Ignite povas esti uzataj sendepende unu de la alia, sed ajna kombinaĵo de ili ankaŭ estas akceptebla. Kompreni kiel ili funkcias permesos al vi determini kiom taŭgaj ili estas por viaj taskoj en via medio kaj kion vi devos oferi kiam vi uzas ilin. Diskopaĝa kunpremo estas desegnita por kunpremi la ĉefan stokadon kaj povas doni mezan kunpremadon. WAL-paĝa momentkunpremado donos mezan gradon de kunpremo por WAL-dosieroj, kaj plej verŝajne eĉ plibonigos rendimenton. WAL-kompaktado ne havos pozitivan efikon al rendimento, sed reduktos la grandecon de WAL-dosieroj kiel eble plej multe per forigo de fizikaj rekordoj.

fonto: www.habr.com

Aldoni komenton