ZFS Basics: Opbevaring og ydeevne

ZFS Basics: Opbevaring og ydeevne

I foråret har vi allerede diskuteret nogle indledende emner, f.eks. hvordan man kontrollerer hastigheden på dine drev и hvad er RAID. I den anden af ​​dem lovede vi endda at fortsætte med at studere ydeevnen af ​​forskellige multi-disk-topologier i ZFS. Dette er næste generations filsystem, der nu implementeres overalt: fra Apple til Ubuntu.

Nå, i dag er den bedste dag at stifte bekendtskab med ZFS, nysgerrige læsere. Bare ved, at efter OpenZFS-udvikler Matt Ahrens ydmyge mening, "er det virkelig svært."

Men før vi når til tallene - og det vil jeg love - for alle muligheder for en ZFS-konfiguration med otte diske, skal vi tale om som Generelt gemmer ZFS data på disken.

Zpool, vdev og enhed

ZFS Basics: Opbevaring og ydeevne
Dette fulde pooldiagram inkluderer tre hjælpe-vdev'er, en af ​​hver klasse og fire til RAIDz2

ZFS Basics: Opbevaring og ydeevne
Der er normalt ingen grund til at oprette en pulje af uoverensstemmende vdev-typer og størrelser - men der er intet, der forhindrer dig i at gøre det, hvis du vil.

For virkelig at forstå ZFS-filsystemet, skal du se nærmere på dets faktiske struktur. For det første forener ZFS de traditionelle niveauer af volumen- og filsystemstyring. For det andet bruger den en transaktionel kopi-på-skriv-mekanisme. Disse funktioner betyder, at systemet er strukturelt meget forskelligt fra konventionelle filsystemer og RAID-arrays. Det første sæt af grundlæggende byggeklodser at forstå er lagerpuljen (zpool), virtuel enhed (vdev) og ægte enhed (enhed).

zpool

Zpool-opbevaringspuljen er den øverste ZFS-struktur. Hver pulje indeholder en eller flere virtuelle enheder. Til gengæld indeholder hver af dem en eller flere rigtige enheder (enhed). Virtuelle pools er selvstændige blokke. En fysisk computer kan indeholde to eller flere separate puljer, men hver er fuldstændig uafhængig af de andre. Puljer kan ikke dele virtuelle enheder.

Redundansen af ​​ZFS er på det virtuelle enhedsniveau, ikke på poolniveauet. Der er absolut ingen redundans på poolniveau - hvis nogen drev vdev eller speciel vdev går tabt, så er hele poolen tabt sammen med det.

Moderne lagerpuljer kan overleve tabet af en cache eller virtuel enhedslog - selvom de kan miste en lille mængde snavsede data, hvis de mister vdev-loggen under en strømafbrydelse eller et systemnedbrud.

Der er en almindelig misforståelse, at ZFS "datastriber" er skrevet på tværs af hele poolen. Det er ikke sandt. Zpool er slet ikke sjov RAID0, den er ret sjov JBOD med en kompleks variabel distributionsmekanisme.

For det meste er posterne fordelt på de tilgængelige virtuelle enheder i henhold til den ledige plads, så i teorien vil de alle blive udfyldt på samme tid. I senere versioner af ZFS tages der højde for den aktuelle vdev-brug (udnyttelse) - hvis en virtuel enhed er væsentligt mere travl end en anden (f.eks. på grund af læsebelastning), springes den midlertidigt over til skrivning, på trods af at den har den højeste ledige enhed pladsforhold.

Den udnyttelsesdetekteringsmekanisme, der er indbygget i moderne ZFS skriveallokeringsmetoder kan reducere latens og øge gennemløbet i perioder med usædvanlig høj belastning - men det er ikke carte blanche på ufrivillig blanding af langsomme HDD'er og hurtige SSD'er i én pulje. En sådan ulige pulje vil stadig fungere med hastigheden af ​​den langsomste enhed, det vil sige som om den var fuldstændig sammensat af sådanne enheder.

vdev

Hver lagerpulje består af en eller flere virtuelle enheder (virtuel enhed, vdev). Til gengæld inkluderer hver vdev en eller flere rigtige enheder. De fleste virtuelle enheder bruges til simpel datalagring, men der er flere vdev-hjælperklasser, inklusive CACHE, LOG og SPECIAL. Hver af disse vdev-typer kan have en af ​​fem topologier: enkelt enhed (enkelt-enhed), RAIDz1, RAIDz2, RAIDz3 eller spejl (spejl).

RAIDz1, RAIDz2 og RAIDz3 er specielle varianter af, hvad oldtimerne ville kalde dobbelt (diagonal) paritet RAID. 1, 2 og 3 henviser til, hvor mange paritetsblokke der er tildelt for hver datastrimmel. I stedet for separate diske for paritet, fordeler virtuelle RAIDz-enheder denne paritet semi-jævnt på tværs af diske. Et RAIDz-array kan miste lige så mange diske, som det har paritetsblokke; hvis den mister endnu en, vil den gå ned og tage opbevaringspuljen med sig.

I spejlede virtuelle enheder (mirror vdev) er hver blok gemt på hver enhed i vdev. Selvom to-brede spejle er de mest almindelige, kan et hvilket som helst vilkårligt antal enheder være i et spejl - tripler bruges ofte i store installationer for forbedret læseydelse og fejltolerance. Et vdev-spejl kan overleve enhver fejl, så længe mindst én enhed i vdev'en fortsætter med at fungere.

Enkelte vdev'er er i sagens natur farlige. En sådan virtuel enhed vil ikke overleve en enkelt fejl - og hvis den bruges som lagring eller en speciel vdev, vil dens fejl føre til ødelæggelse af hele poolen. Vær meget, meget forsigtig her.

CACHE, LOG og SPECIAL VA'er kan oprettes ved hjælp af enhver af ovenstående topologier - men husk at tabet af en SPECIAL VA betyder tab af poolen, så en redundant topologi anbefales stærkt.

enhed

Dette er nok det nemmeste udtryk at forstå i ZFS - det er bogstaveligt talt en blokeret tilfældig adgangsenhed. Husk, at virtuelle enheder består af individuelle enheder, mens en pulje består af virtuelle enheder.

Diske - enten magnetiske eller solid state - er de mest almindelige blokenheder, der bruges som byggesten i vdev. Men enhver enhed med en deskriptor i /dev vil gøre det, så hele hardware RAID-arrays kan bruges som separate enheder.

En simpel råfil er en af ​​de vigtigste alternative blokenheder, som en vdev kan bygges ud fra. Testpuljer fra sparsomme filer er en meget praktisk måde at kontrollere poolkommandoer og se, hvor meget plads der er tilgængelig i en pool eller virtuel enhed med en given topologi.

ZFS Basics: Opbevaring og ydeevne
Du kan oprette en testpulje fra sparsomme filer på få sekunder - men glem ikke at slette hele poolen og dens komponenter bagefter

Lad os sige, at du vil sætte en server på otte diske og planlægger at bruge 10 TB diske (~9300 GiB) - men du er ikke sikker på, hvilken topologi der passer bedst til dine behov. I eksemplet ovenfor bygger vi en testpulje fra sparsomme filer på få sekunder - og nu ved vi, at en RAIDz2 vdev på otte 10 TB diske giver 50 TiB brugbar kapacitet.

En anden speciel klasse af enheder er SPARE (reserve). Hot-swap-enheder tilhører, i modsætning til almindelige enheder, hele puljen og ikke til en enkelt virtuel enhed. Hvis en vdev i puljen fejler, og en ekstra enhed er forbundet til puljen og tilgængelig, vil den automatisk slutte sig til den berørte vdev.

Efter at have oprettet forbindelse til den berørte vdev, begynder reserveenheden at modtage kopier eller rekonstruktioner af de data, der skulle være på den manglende enhed. I traditionel RAID kaldes dette rebuilding, mens det i ZFS kaldes resilvering.

Det er vigtigt at bemærke, at reserveenheder ikke permanent erstatter defekte enheder. Dette er kun en midlertidig erstatning for at reducere mængden af ​​tid vdev forringes. Efter at administratoren har erstattet den mislykkede vdev, gendannes redundans til den permanente enhed, og SPARE afbrydes fra vdev'en og returneres til at fungere som reserve for hele poolen.

Datasæt, blokke og sektorer

Det næste sæt byggeklodser, der skal forstås på vores ZFS-rejse, handler mindre om hardwaren og mere om, hvordan selve dataene er organiseret og gemt. Vi springer et par niveauer over her - såsom metaslab - for ikke at rode i detaljerne og samtidig bevare en forståelse af den overordnede struktur.

Datasæt (datasæt)

ZFS Basics: Opbevaring og ydeevne
Når vi først opretter et datasæt, viser det al tilgængelig poolplads. Så sætter vi kvoten – og ændrer monteringspunktet. Magi!

ZFS Basics: Opbevaring og ydeevne
Zvol er for det meste bare et datasæt, der er fjernet fra dets filsystemlag, som vi her erstatter med et helt normalt ext4-filsystem.

Et ZFS-datasæt er nogenlunde det samme som et standardmonteret filsystem. Som et almindeligt filsystem ser det ved første øjekast ud som "bare endnu en mappe". Men ligesom almindelige monterbare filsystemer har hvert ZFS-datasæt sit eget sæt grundlæggende egenskaber.

Først og fremmest kan et datasæt have en tildelt kvote. Hvis indstillet zfs set quota=100G poolname/datasetname, så vil du ikke være i stand til at skrive til den monterede mappe /poolname/datasetname mere end 100 GiB.

Læg mærke til tilstedeværelsen - og fraværet - af skråstreger i begyndelsen af ​​hver linje? Hvert datasæt har sin egen plads i både ZFS-hierarkiet og systemmonteringshierarkiet. Der er ingen indledende skråstreg i ZFS-hierarkiet - du starter med puljenavnet og derefter stien fra et datasæt til det næste. For eksempel, pool/parent/child for et datasæt navngivet child under det overordnede datasæt parent i en pool med et kreativt navn pool.

Som standard vil datasættets monteringspunkt svare til dets navn i ZFS-hierarkiet med en ledende skråstreg - puljen med navnet pool monteret som /pool, datasæt parent monteret i /pool/parent, og det underordnede datasæt child monteret i /pool/parent/child. Datasættets systemmonteringspunkt kan dog ændres.

Hvis vi specificerer zfs set mountpoint=/lol pool/parent/child, derefter datasættet pool/parent/child monteret på systemet som /lol.

Ud over datasæt bør vi nævne volumener (zvols). Et volumen er nogenlunde det samme som et datasæt, bortset fra at det faktisk ikke har et filsystem – det er bare en blokenhed. Du kan f.eks. oprette zvol Med navn mypool/myzvol, formater det derefter med et ext4-filsystem, og montér derefter det filsystem - du har nu et ext4-filsystem, men med alle sikkerhedsfunktionerne i ZFS! Dette kan virke dumt på en enkelt maskine, men giver meget mere mening som backend, når du eksporterer en iSCSI-enhed.

blokke

ZFS Basics: Opbevaring og ydeevne
Filen er repræsenteret af en eller flere blokke. Hver blok er gemt på én virtuel enhed. Blokstørrelsen er normalt lig med parameteren rekordstørrelse, men kan reduceres til 2^skiftehvis den indeholder metadata eller en lille fil.

ZFS Basics: Opbevaring og ydeevne
Vi virkelig virkelig ikke spøg med den enorme præstationsstraf, hvis du sætter for lille forskydning

I en ZFS-pulje er alle data, inklusive metadata, gemt i blokke. Den maksimale blokstørrelse for hvert datasæt er defineret i egenskaben recordsize (rekordstørrelse). Poststørrelsen kan ændres, men dette vil ikke ændre størrelsen eller placeringen af ​​blokke, der allerede er skrevet til datasættet - det påvirker kun nye blokke, efterhånden som de skrives.

Medmindre andet er angivet, er den aktuelle standardpoststørrelse 128 KiB. Det er en lidt vanskelig afvejning, hvor ydeevnen ikke er perfekt, men den er heller ikke forfærdelig i de fleste tilfælde. Recordsize kan indstilles til enhver værdi fra 4K til 1M (med avancerede indstillinger recordsize du kan installere endnu mere, men det er sjældent en god idé).

Enhver blok refererer til dataene i kun én fil - du kan ikke proppe to forskellige filer ind i én blok. Hver fil består af en eller flere blokke, afhængigt af størrelsen. Hvis filstørrelsen er mindre end poststørrelsen, vil den blive gemt i en mindre blokstørrelse - for eksempel vil en blok med en 2 KiB fil kun optage én 4 KiB sektor på disken.

Hvis filen er stor nok og kræver flere blokke, vil alle poster med denne fil være af størrelse recordsize - inklusive den sidste post, hvis hoveddel evt ubrugt plads.

zvols har ikke en ejendom recordsize — i stedet har de en tilsvarende ejendom volblocksize.

Sektorer

Den sidste, mest basale byggesten er sektoren. Det er den mindste fysiske enhed, der kan skrives til eller læses fra den underliggende enhed. I flere årtier brugte de fleste diske 512-byte sektorer. For nylig er de fleste diske sat til 4 KiB-sektorer, og nogle - især SSD'er - har 8 KiB-sektorer eller endnu mere.

ZFS-systemet har en egenskab, der giver dig mulighed for manuelt at indstille sektorstørrelsen. Denne ejendom ashift. Noget forvirrende er shift en magt af to. For eksempel, ashift=9 betyder en sektorstørrelse på 2^9 eller 512 bytes.

ZFS forespørger operativsystemet for detaljerede oplysninger om hver blokenhed, når den føjes til en ny vdev, og teoretisk installerer ashift automatisk korrekt baseret på disse oplysninger. Desværre lyver mange drev om deres sektorstørrelse for at bevare kompatibiliteten med Windows XP (som ikke var i stand til at forstå drev med andre sektorstørrelser).

Dette betyder, at en ZFS-administrator kraftigt rådes til at kende den faktiske sektorstørrelse på deres enheder og indstilles manuelt ashift. Hvis ashift er sat for lavt, så stiger antallet af læse/skrive-operationer astronomisk. Så at skrive 512-byte "sektorer" ind i en rigtig 4 KiB sektor betyder at skulle skrive den første "sektor", derefter læse 4 KiB-sektoren, ændre den med en anden 512-byte "sektor", skrive den tilbage til den nye 4 KiB sektor osv. for hver post.

I den virkelige verden rammer en sådan straf Samsung EVO SSD'er, for hvilke ashift=13, men disse SSD'er lyver om deres sektorstørrelse, og derfor er standarden sat til ashift=9. Hvis en erfaren systemadministrator ikke ændrer denne indstilling, så virker denne SSD langsommere konventionel magnetisk HDD.

Til sammenligning, for stor størrelse ashift der er praktisk talt ingen straf. Der er ingen reel præstationsstraf, og stigningen i ubrugt plads er uendelig lille (eller nul med komprimering aktiveret). Derfor anbefaler vi kraftigt, at selv de drev, der bruger 512-byte sektorer, installeres ashift=12 eller ashift=13at møde fremtiden med tillid.

Ejendom ashift er indstillet for hver virtuel vdev-enhed, og ikke til poolen, som mange fejlagtigt tror - og ændrer sig ikke efter installationen. Hvis du ved et uheld rammer ashift når du tilføjer en ny vdev til en pool, har du uigenkaldeligt forurenet poolen med en lavtydende enhed, og der er normalt ikke andet valg end at ødelægge poolen og starte forfra. Selv fjernelse af vdev vil ikke redde dig fra en ødelagt konfiguration ashift!

Kopi-på-skriv-mekanisme

ZFS Basics: Opbevaring og ydeevne
Hvis et almindeligt filsystem skal overskrive data, ændrer det hver blok, hvor det er

ZFS Basics: Opbevaring og ydeevne
Et kopi-på-skriv-filsystem skriver en ny blokversion og låser derefter den gamle version op

ZFS Basics: Opbevaring og ydeevne
I det abstrakte, hvis vi ignorerer den faktiske fysiske placering af blokkene, så er vores "datakomet" forenklet til en "dataorm", der bevæger sig fra venstre mod højre hen over kortet over tilgængelig plads

ZFS Basics: Opbevaring og ydeevne
Nu kan vi få en god idé om, hvordan copy-on-write snapshots fungerer - hver blok kan tilhøre flere snapshots og vil vare ved, indtil alle tilknyttede snapshots er ødelagt

Copy on Write (CoW) mekanismen er det grundlæggende grundlag for, hvad der gør ZFS til et så fantastisk system. Grundkonceptet er enkelt - hvis du beder et traditionelt filsystem om at ændre en fil, vil det gøre præcis, hvad du bad om. Hvis du beder et kopi-på-skriv-filsystem om at gøre det samme, vil det sige "ok", men lyve for dig.

I stedet skriver et kopi-på-skriv-filsystem en ny version af den ændrede blok og opdaterer derefter filens metadata for at fjerne linket til den gamle blok og knytte den nye blok, du lige har skrevet, til den.

Afmontering af den gamle blok og sammenkædning af den nye sker i én operation, så den kan ikke afbrydes - hvis du slukker efter dette er sket, har du en ny version af filen, og hvis du slukker tidligt, har du den gamle version . Under alle omstændigheder vil der ikke være nogen konflikter i filsystemet.

Copy-on-write i ZFS forekommer ikke kun på filsystemniveau, men også på diskstyringsniveau. Dette betyder, at ZFS ikke påvirkes af hvidt mellemrum (et hul i RAID'en) - et fænomen, hvor strimlen kun nåede at optage delvist, før systemet gik ned, med array-skade efter en genstart. Her er striben skrevet atomisk, vdev er altid sekventiel, og Bob er din onkel.

ZIL: ZFS hensigtslog

ZFS Basics: Opbevaring og ydeevne
ZFS-systemet behandler synkrone skrivninger på en særlig måde - det gemmer dem midlertidigt, men øjeblikkeligt, i ZIL, før de senere skrives permanent sammen med asynkrone skrivninger.

ZFS Basics: Opbevaring og ydeevne
Typisk bliver data skrevet til en ZIL aldrig læst igen. Men det er muligt efter et systemnedbrud

ZFS Basics: Opbevaring og ydeevne
SLOG, eller sekundær LOG-enhed, er blot en speciel - og gerne meget hurtig - vdev, hvor ZIL kan opbevares adskilt fra hovedlageret

ZFS Basics: Opbevaring og ydeevne
Efter et nedbrud afspilles alle beskidte data i ZIL - i dette tilfælde er ZIL på SLOG, så det afspilles derfra

Der er to hovedkategorier af skriveoperationer - synkron (synkron) og asynkron (asynkron). For de fleste arbejdsbelastninger er langt de fleste skrivninger asynkrone - filsystemet tillader dem at blive aggregeret og udgivet i batches, hvilket reducerer fragmentering og øger gennemstrømningen markant.

Synkroniserede optagelser er en helt anden sag. Når en applikation anmoder om en synkron skrivning, fortæller den filsystemet: "Du skal overgive dette til ikke-flygtig hukommelse lige nuindtil da er der ikke andet, jeg kan gøre." Derfor bør synkrone skrivninger committeres til disk med det samme - og hvis det øger fragmenteringen eller reducerer gennemløbet, så må det være sådan.

ZFS håndterer synkrone skrivninger anderledes end almindelige filsystemer - i stedet for straks at forpligte dem til almindelig lagring, forpligter ZFS dem til et særligt lagerområde kaldet ZFS Intent Log eller ZIL. Tricket er, at disse optegnelser også forblive i hukommelsen og aggregeres sammen med normale asynkrone skriveanmodninger, for senere at blive tømt til lageret som helt normale TXG'er (Transaction Groups).

Ved normal drift skrives ZIL til og læses aldrig igen. Når posterne fra ZIL'en efter nogle få øjeblikke er commiteret til hovedlageret i almindelige TXG'er fra RAM, bliver de løsrevet fra ZIL'en. Den eneste gang, der læses noget fra ZIL, er når poolen importeres.

Hvis ZFS fejler - et operativsystemnedbrud eller en strømafbrydelse - mens der er data i ZIL, vil disse data blive læst under den næste poolimport (for eksempel ved genstart af nødsystemet). Alt i ZIL vil blive læst, grupperet i TXG'er, forpligtet til hovedlageret og derefter adskilt fra ZIL'en under importprocessen.

En af vdev-hjælperklasserne kaldes LOG eller SLOG, den sekundære enhed i LOG. Det har ét formål - at forsyne poolen med en separat, og helst meget hurtigere, meget skrivebestandig vdev til at gemme ZIL'en, i stedet for at gemme ZIL'en på den primære vdev-butik. Selve ZIL'en opfører sig på samme måde, uanset hvor den er gemt, men hvis LOG vdev'en har meget høj skriveydelse, vil synkronskrivning være hurtigere.

Tilføjelse af en vdev med LOG til puljen virker ikke kan ikke forbedre asynkron skrive ydeevne - også selvom du tvinger alle skrivninger til ZIL med zfs set sync=always, vil de stadig være knyttet til hovedlageret i TXG på samme måde og i samme tempo som uden loggen. Den eneste direkte forbedring af ydeevnen er latensen af ​​synkrone skrivninger (fordi hurtigere log fremskynder operationer). sync).

Men i et miljø, der allerede kræver mange synkrone skrivninger, kan vdev LOG indirekte fremskynde asynkron skrivning og ikke-cache læsning. Aflastning af ZIL-poster til en separat vdev LOG betyder mindre strid for IOPS på primær lagring, hvilket forbedrer ydeevnen af ​​alle læsninger og skrivninger til en vis grad.

Snapshots

Kopier-på-skriv-mekanismen er også et nødvendigt grundlag for ZFS-atomiske snapshots og inkrementel asynkron replikation. Det aktive filsystem har et pointertræ, der markerer alle poster med aktuelle data - når du tager et snapshot, laver du blot en kopi af dette pointertræ.

Når en post overskrives på det aktive filsystem, skriver ZFS først den nye blokversion til ubrugt plads. Det frigør derefter den gamle version af blokken fra det aktuelle filsystem. Men hvis et øjebliksbillede refererer til den gamle blok, forbliver den stadig uændret. Den gamle blok vil faktisk ikke blive gendannet som ledig plads, før alle snapshots, der refererer til denne blok, er ødelagt!

Replikation

ZFS Basics: Opbevaring og ydeevne
Mit Steam-bibliotek i 2015 var på 158 GiB og inkluderede 126 filer. Dette er ret tæt på den optimale situation for rsync - ZFS-replikering over netværket var "kun" 927 % hurtigere.

ZFS Basics: Opbevaring og ydeevne
På det samme netværk er replikering af en enkelt 40 GB Windows 7-virtuel maskine-billedfil en helt anden historie. ZFS-replikering er 289 gange hurtigere end rsync - eller "kun" 161 gange hurtigere, hvis du er smart nok til at kalde rsync med --inplace.

ZFS Basics: Opbevaring og ydeevne
Når et VM-billede skaleres, udløser rsync skalering med det. 1,9 TiB er ikke så stor for et moderne VM-billede - men det er stort nok til, at ZFS-replikering er 1148 gange hurtigere end rsync, selv med rsyncs --inplace-argument

Når du først forstår, hvordan snapshots fungerer, burde det være nemt at forstå essensen af ​​replikering. Da et øjebliksbillede blot er et træ af pejlemærker til poster, følger det, at hvis vi gør det zfs send snapshot, så sender vi både dette træ og alle poster, der er knyttet til det. Når vi sender dette zfs send в zfs receive på målet skriver den både det faktiske indhold af blokken og træet af pegepinde, der refererer til blokkene til måldatasættet.

Tingene bliver endnu mere interessante på den anden zfs send. Vi har nu to systemer, som hver indeholder poolname/datasetname@1, og du tager et nyt øjebliksbillede poolname/datasetname@2. Derfor har du i den originale pool datasetname@1 и datasetname@2, og i målpuljen indtil videre kun det første øjebliksbillede datasetname@1.

Da vi har et fælles øjebliksbillede mellem kilden og målet datasetname@1, vi kan gøre det trinvis zfs send over det. Når vi siger til systemet zfs send -i poolname/datasetname@1 poolname/datasetname@2, sammenligner den to pointertræer. Eventuelle pointer, der kun findes i @2, henviser naturligvis til nye blokke - så vi har brug for indholdet af disse blokke.

På et fjernsystem behandler en trinvis send lige så simpelt. Først skriver vi alle nye poster inkluderet i strømmen send, og tilføj derefter pointere til disse blokke. Voila, det har vi @2 i det nye system!

ZFS asynkron inkrementel replikering er en enorm forbedring i forhold til tidligere ikke-snapshot-baserede metoder såsom rsync. I begge tilfælde overføres kun ændrede data - men rsync skal først læse fra disken alle data på begge sider for at kontrollere summen og sammenligne den. I modsætning hertil læser ZFS-replikering ikke andet end pointertræer - og alle blokke, der ikke er til stede i det delte snapshot.

Indbygget kompression

Kopier-på-skriv-mekanismen forenkler også inline-komprimeringssystemet. I et traditionelt filsystem er komprimering problematisk - både den gamle version og den nye version af de ændrede data ligger på samme plads.

Hvis vi betragter et stykke data i midten af ​​en fil, der starter livet som en megabyte af nuller fra 0x00000000 og så videre, er det meget nemt at komprimere det til én sektor på disken. Men hvad sker der, hvis vi erstatter den megabyte af nuller med en megabyte af ukomprimerbare data som JPEG eller pseudo-tilfældig støj? Uventet vil denne megabyte af data ikke kræve én, men 256 4 KiB-sektorer, og på dette sted på disken er kun én sektor reserveret.

ZFS har ikke dette problem, da ændrede poster altid skrives til ubrugt plads - den oprindelige blok optager kun én 4 KiB sektor, og den nye post vil optage 256, men dette er ikke et problem - et nyligt ændret fragment fra " midten" af filen ville blive skrevet til ubrugt plads, uanset om dens størrelse er ændret eller ej, så for ZFS er dette en ganske almindelig situation.

Native ZFS-komprimering er deaktiveret som standard, og systemet tilbyder pluggbare algoritmer - i øjeblikket LZ4, gzip (1-9), LZJB og ZLE.

  • LZ4 er en streaming-algoritme, der tilbyder ekstremt hurtig komprimering og dekompression og ydeevnefordele til de fleste anvendelsestilfælde - selv på ret langsomme CPU'er.
  • GZIP er en ærværdig algoritme, som alle Unix-brugere kender og elsker. Den kan implementeres med komprimeringsniveauer 1-9, hvor komprimeringsforhold og CPU-forbrug stiger, når det nærmer sig niveau 9. Algoritmen er velegnet til alle tekst- (eller andre meget komprimerbare) use cases, men forårsager ellers ofte CPU-problemer − brug den med omhu, især på højere niveauer.
  • LZJB er den originale algoritme i ZFS. Den er forældet og bør ikke længere bruges, LZ4 overgår den på alle måder.
  • DÅRLIGT - nul niveau kodning, nul niveau kodning. Den rører slet ikke normale data, men komprimerer store sekvenser af nuller. Nyttigt til fuldstændigt inkomprimerbare datasæt (såsom JPEG, MP4 eller andre allerede komprimerede formater), da det ignorerer inkomprimerbare data, men komprimerer ubrugt plads i de resulterende poster.

Vi anbefaler LZ4-komprimering til næsten alle anvendelsestilfælde; præstationsstraffen, når du støder på ukomprimerbare data, er meget lille, og vækst ydeevne for typiske data er betydelig. Kopiering af et virtuel maskinebillede til en ny installation af Windows-operativsystemet (nyinstalleret OS, ingen data inde endnu) med compression=lz4 passerede 27 % hurtigere end med compression=noneI denne test i 2015.

ARC - adaptiv erstatningscache

ZFS er det eneste moderne filsystem, vi kender til, som bruger sin egen læse-caching-mekanisme i stedet for at stole på operativsystemets sidecache til at gemme kopier af nyligt læste blokke i RAM.

Selvom den native cache ikke er uden problemer - kan ZFS ikke reagere på nye anmodninger om hukommelsesallokering lige så hurtigt som kernen, så den nye udfordring malloc() på hukommelsesallokering kan mislykkes, hvis den har brug for den RAM, der i øjeblikket er optaget af ARC. Men der er gode grunde til at bruge din egen cache, i hvert fald indtil videre.

Alle kendte moderne operativsystemer, inklusive MacOS, Windows, Linux og BSD, bruger LRU (Least Recently Used) algoritmen til at implementere sidecachen. Dette er en primitiv algoritme, der skubber den cachelagrede blok "op i køen" efter hver læsning, og skubber blokkene "ned i køen" efter behov for at tilføje nye cache-misser (blokke, der skulle have været læst fra disken, ikke fra cachen) op.

Algoritmen fungerer normalt fint, men på systemer med store fungerende datasæt fører LRU nemt til thrashing - udelukker ofte nødvendige blokke for at give plads til blokke, der aldrig vil blive læst fra cachen igen.

ARC er en meget mindre naiv algoritme, der kan opfattes som en "vægtet" cache. Hver gang en cachelagret blok læses, bliver den lidt "tyngre" og sværere at smide ud - og endda efter at have smidt en blok ud spores inden for et vist tidsrum. En blok, der er blevet smidt ud, men derefter skal læses tilbage i cachen, bliver også "tyngre".

Slutresultatet af alt dette er en cache med et meget højere hit-forhold, forholdet mellem cache-hits (læsninger udført fra cachen) og cache-misser (læser fra disk). Dette er en ekstremt vigtig statistik - ikke kun er selve cache-hits serveret i størrelsesordener hurtigere, cache-misser kan også serveres hurtigere, da jo flere cache-hits, jo færre samtidige diskanmodninger og jo lavere forsinkelse for de resterende miss, der skal serveres med disk.

Konklusion

Efter at have lært den grundlæggende semantik af ZFS - hvordan kopiering-på-skriv fungerer, såvel som forholdet mellem lagerpuljer, virtuelle enheder, blokke, sektorer og filer - er vi klar til at diskutere den virkelige verden ydeevne med rigtige tal.

I den næste del tager vi et kig på den faktiske ydeevne af puljer med spejlede vdev'er og RAIDz, i forhold til hinanden, og også i forhold til de traditionelle Linux-kerne RAID-topologier, vi har udforsket. tidligere.

Først ville vi kun dække det grundlæggende - selve ZFS-topologierne - men derefter sådan en lad os gøre os klar til at tale om mere avanceret opsætning og tuning af ZFS, inklusive brugen af ​​ekstra vdev-typer såsom L2ARC, SLOG og Special Allocation.

Kilde: www.habr.com

Tilføj en kommentar