ZFS Basics: Lagring och prestanda

ZFS Basics: Lagring och prestanda

I vår har vi redan diskuterat några inledande ämnen, t.ex. hur du kontrollerar hastigheten på dina enheter и vad är RAID. I den andra av dem lovade vi till och med att fortsätta studera prestandan för olika multidisktopologier i ZFS. Detta är nästa generations filsystem som nu implementeras överallt: från Apple до ubuntu.

Tja, idag är den bästa dagen att bekanta sig med ZFS, nyfikna läsare. Vet bara att enligt OpenZFS-utvecklaren Matt Ahrens ödmjuka åsikt "är det verkligen svårt."

Men innan vi kommer till siffrorna - och de kommer, jag lovar - för alla alternativ för en ZFS-konfiguration med åtta diskar, måste vi prata om как I allmänhet lagrar ZFS data på disk.

Zpool, vdev och enhet

ZFS Basics: Lagring och prestanda
Detta fullständiga pooldiagram inkluderar tre extra vdevs, en av varje klass och fyra för RAIDz2

ZFS Basics: Lagring och prestanda
Det finns vanligtvis ingen anledning att skapa en pool av omatchade vdev-typer och storlekar - men det finns inget som hindrar dig från att göra det om du vill.

För att verkligen förstå ZFS-filsystemet måste du ta en närmare titt på dess faktiska struktur. För det första förenar ZFS de traditionella nivåerna av volym- och filsystemhantering. För det andra använder den en transaktionell kopiera-på-skriv-mekanism. Dessa funktioner gör att systemet strukturellt skiljer sig mycket från konventionella filsystem och RAID-arrayer. Den första uppsättningen grundläggande byggstenar att förstå är lagringspoolen (zpool), virtuell enhet (vdev) och riktig enhet (enhet).

zpool

Zpool-lagringspoolen är den översta ZFS-strukturen. Varje pool innehåller en eller flera virtuella enheter. I sin tur innehåller var och en av dem en eller flera riktiga enheter (enhet). Virtuella pooler är fristående block. En fysisk dator kan innehålla två eller flera separata pooler, men var och en är helt oberoende av de andra. Pooler kan inte dela virtuella enheter.

Redundansen för ZFS är på virtuell enhetsnivå, inte på poolnivå. Det finns absolut ingen redundans på poolnivå - om någon enhet vdev eller speciell vdev går förlorad, så förloras hela poolen tillsammans med den.

Moderna lagringspooler kan överleva förlusten av en cache eller virtuell enhetslogg - även om de kan förlora en liten mängd smutsig data om de tappar vdev-loggen under ett strömavbrott eller systemkrasch.

Det finns en vanlig missuppfattning att ZFS "data stripes" skrivs över hela poolen. Det är inte sant. Zpool är inte alls rolig RAID0, det är ganska roligt JBOD med en komplex variabel distributionsmekanism.

För det mesta är posterna fördelade på tillgängliga virtuella enheter enligt tillgängligt ledigt utrymme, så i teorin kommer de alla att fyllas samtidigt. I senare versioner av ZFS tas den aktuella vdev-användningen (användningen) med i beräkningen - om en virtuell enhet är betydligt mer upptagen än en annan (till exempel på grund av läsbelastning) kommer den tillfälligt att hoppas över för skrivning, trots att den har den högsta lediga utrymmesförhållande.

Mekanismen för användningsdetektering inbyggd i moderna ZFS-skrivallokeringsmetoder kan minska latensen och öka genomströmningen under perioder med ovanligt hög belastning - men det är inte blankofullmakt på ofrivillig blandning av långsamma hårddiskar och snabba SSD:er i en pool. En sådan ojämlik pool kommer fortfarande att fungera med hastigheten för den långsammaste enheten, det vill säga som om den var helt sammansatt av sådana enheter.

vdev

Varje lagringspool består av en eller flera virtuella enheter (virtuell enhet, vdev). I sin tur innehåller varje vdev en eller flera riktiga enheter. De flesta virtuella enheter används för enkel datalagring, men det finns flera vdev-hjälparklasser, inklusive CACHE, LOG och SPECIAL. Var och en av dessa vdev-typer kan ha en av fem topologier: enkel enhet (enkel enhet), RAIDz1, RAIDz2, RAIDz3 eller spegel (spegel).

RAIDz1, RAIDz2 och RAIDz3 är speciella varianter av vad de gamla skulle kalla RAID med dubbel (diagonal) paritet. 1, 2 och 3 hänvisar till hur många paritetsblock som är tilldelade för varje dataremsa. Istället för separata diskar för paritet fördelar virtuella RAIDz-enheter denna paritet halvjämnt över diskarna. En RAIDz-array kan förlora lika många diskar som den har paritetsblock; om den tappar en till kommer den att krascha och ta med sig lagringspoolen.

I speglade virtuella enheter (mirror vdev) lagras varje block på varje enhet i vdev. Även om två breda speglar är vanligast, kan vilket godtyckligt antal enheter som helst finnas i en spegel – tripplar används ofta i stora installationer för förbättrad läsprestanda och feltolerans. En vdev-spegel kan överleva alla fel så länge som minst en enhet i vdev fortsätter att fungera.

Enstaka vdevs är i sig farliga. En sådan virtuell enhet kommer inte att överleva ett enda fel - och om den används som lagring eller en speciell vdev, kommer dess fel att leda till att hela poolen förstörs. Var väldigt, väldigt försiktig här.

CACHE, LOG och SPECIAL VA kan skapas med någon av ovanstående topologier - men kom ihåg att förlusten av en SPECIAL VA innebär förlust av poolen, så en redundant topologi rekommenderas starkt.

anordning

Detta är förmodligen den enklaste termen att förstå i ZFS - det är bokstavligen en blockerad enhet för direktåtkomst. Kom ihåg att virtuella enheter består av individuella enheter, medan en pool består av virtuella enheter.

Diskar - antingen magnetiska eller solid state - är de vanligaste blockenheterna som används som byggstenar i vdev. Men vilken enhet som helst med en deskriptor i /dev duger, så hela hårdvaru-RAID-arrayer kan användas som separata enheter.

En enkel råfil är en av de viktigaste alternativa blockenheterna som en vdev kan byggas från. Testpooler från glesa filer är ett mycket praktiskt sätt att kontrollera poolkommandon och se hur mycket utrymme som är tillgängligt i en pool eller virtuell enhet med en given topologi.

ZFS Basics: Lagring och prestanda
Du kan skapa en testpool från glesa filer på bara några sekunder - men glöm inte att radera hela poolen och dess komponenter efteråt

Låt oss säga att du vill sätta en server på åtta diskar och planerar att använda 10 TB diskar (~9300 GiB) - men du är inte säker på vilken topologi som passar dina behov bäst. I exemplet ovan bygger vi en testpool från glesa filer på några sekunder – och nu vet vi att en RAIDz2 vdev på åtta 10 TB diskar ger 50 TiB användbar kapacitet.

En annan speciell klass av enheter är SPARE (reserv). Hot-swap-enheter, till skillnad från vanliga enheter, tillhör hela poolen och inte till en enda virtuell enhet. Om en vdev i poolen misslyckas och en reservenhet är ansluten till poolen och tillgänglig, kommer den automatiskt att ansluta sig till den berörda vdev.

Efter anslutning till den berörda vdev-enheten börjar reservenheten ta emot kopior eller rekonstruktioner av data som ska finnas på den saknade enheten. I traditionell RAID kallas detta rebuilding, medan det i ZFS kallas resilvering.

Det är viktigt att notera att reservenheter inte permanent ersätter defekta enheter. Detta är bara en tillfällig ersättning för att minska tiden vdev försämras. Efter att administratören har ersatt den misslyckade vdev:n, återställs redundansen till den permanenta enheten, och SPARE kopplas bort från vdev:n och återgår till att fungera som reserv för hela poolen.

Datauppsättningar, block och sektorer

Nästa uppsättning byggstenar att förstå på vår ZFS-resa handlar mindre om hårdvaran och mer om hur själva data organiseras och lagras. Vi hoppar över några nivåer här - som metaslab - för att inte röra ner detaljerna samtidigt som vi har en förståelse för den övergripande strukturen.

Datauppsättning (datauppsättning)

ZFS Basics: Lagring och prestanda
När vi först skapar en datauppsättning visar den allt tillgängligt poolutrymme. Sedan sätter vi kvoten – och ändrar monteringspunkten. Magi!

ZFS Basics: Lagring och prestanda
Zvol är för det mesta bara en datauppsättning avskalad från dess filsystemlager, som vi här ersätter med ett helt normalt ext4-filsystem.

En ZFS-datauppsättning är ungefär densamma som ett standardmonterat filsystem. Som ett vanligt filsystem ser det vid första anblicken ut som "bara en annan mapp". Men precis som vanliga monterbara filsystem har varje ZFS-dataset sin egen uppsättning grundläggande egenskaper.

Först och främst kan en datauppsättning ha en tilldelad kvot. Om inställt zfs set quota=100G poolname/datasetname, då kommer du inte att kunna skriva till den monterade mappen /poolname/datasetname mer än 100 GiB.

Lägger du märke till förekomsten - och frånvaron - av snedstreck i början av varje rad? Varje datauppsättning har sin egen plats i både ZFS-hierarkin och systemmonteringshierarkin. Det finns inget inledande snedstreck i ZFS-hierarkin - du börjar med poolnamnet och sedan sökvägen från en datauppsättning till nästa. Till exempel, pool/parent/child för en datauppsättning som heter child under det överordnade datasetet parent i en pool med ett kreativt namn pool.

Som standard kommer datasetets monteringspunkt att vara likvärdig med dess namn i ZFS-hierarkin, med ett ledande snedstreck - poolen med namnet pool monterad som /pool, datauppsättning parent monterad i /pool/parent, och den underordnade datamängden child monterad i /pool/parent/child. Datauppsättningens systemmonteringspunkt kan dock ändras.

Om vi ​​specificerar zfs set mountpoint=/lol pool/parent/child, sedan datamängden pool/parent/child monterad på systemet som /lol.

Förutom datauppsättningar bör vi nämna volymer (zvols). En volym är ungefär densamma som en datauppsättning, förutom att den faktiskt inte har något filsystem – det är bara en blockenhet. Du kan till exempel skapa zvol Med namn mypool/myzvol, formatera det sedan med ett ext4-filsystem och montera sedan det filsystemet - du har nu ett ext4-filsystem, men med alla säkerhetsfunktioner i ZFS! Detta kan verka dumt på en enda maskin, men är mycket mer meningsfullt som en backend när du exporterar en iSCSI-enhet.

Blocks

ZFS Basics: Lagring och prestanda
Filen representeras av ett eller flera block. Varje block lagras på en virtuell enhet. Blockstorleken är vanligtvis lika med parametern rekordstorlek, men kan reduceras till 2^skifteom den innehåller metadata eller en liten fil.

ZFS Basics: Lagring och prestanda
Vi verkligen verkligen inte skämta om det enorma prestationsstraffet om du ställer in för liten växling

I en ZFS-pool lagras all data, inklusive metadata, i block. Den maximala blockstorleken för varje datamängd definieras i egenskapen recordsize (rekordstorlek). Poststorleken kan ändras, men detta kommer inte att ändra storleken eller platsen för några block som redan har skrivits till datasetet - det påverkar bara nya block när de skrivs.

Om inget annat anges är den nuvarande standardpoststorleken 128 KiB. Det är lite av en knepig avvägning där prestanda inte är perfekt, men det är inte hemskt i de flesta fall heller. Recordsize kan ställas in på valfritt värde från 4K till 1M (med avancerade inställningar recordsize du kan installera ännu mer, men det är sällan en bra idé).

Alla block hänvisar till data från endast en fil - du kan inte klämma in två olika filer i ett block. Varje fil består av ett eller flera block, beroende på storleken. Om filstorleken är mindre än poststorleken kommer den att lagras i en mindre blockstorlek - till exempel kommer ett block med en 2 KiB fil att uppta endast en 4 KiB sektor på disken.

Om filen är tillräckligt stor och kräver flera block, kommer alla poster med denna fil att vara av storlek recordsize - inklusive den sista posten, vars huvuddel kan vara oanvänt utrymme.

zvols har ingen fastighet recordsize — i stället har de en likvärdig egenskap volblocksize.

Sektorer

Den sista, mest grundläggande byggstenen är sektorn. Det är den minsta fysiska enheten som kan skrivas till eller läsas från den underliggande enheten. Under flera decennier använde de flesta diskar 512-byte sektorer. Nyligen har de flesta diskar konfigurerats för 4 KiB-sektorer, och vissa - särskilt SSD-enheter - har 8 KiB-sektorer eller till och med mer.

ZFS-systemet har en egenskap som låter dig ställa in sektorstorleken manuellt. Denna fastighet ashift. Något förvirrande är shift en tvåpotens. Till exempel, ashift=9 betyder en sektorstorlek på 2^9 eller 512 byte.

ZFS frågar efter detaljerad information om varje blockenhet i operativsystemet när den läggs till i en ny vdev, och teoretiskt sett installerar den automatiskt ashift korrekt baserat på den informationen. Tyvärr ljuger många enheter om sin sektorstorlek för att bibehålla kompatibiliteten med Windows XP (som inte kunde förstå enheter med andra sektorstorlekar).

Detta innebär att en ZFS-administratör starkt rekommenderas att känna till den faktiska sektorstorleken på sina enheter och ställa in dem manuellt ashift. Om växlingen är inställd för lågt ökar antalet läs-/skrivoperationer astronomiskt. Så att skriva 512-byte "sektorer" till en riktig 4 KiB-sektor innebär att man måste skriva den första "sektorn", sedan läsa 4 KiB-sektorn, modifiera den med en andra 512-byte "sektor", skriva tillbaka den till den nya 4 KiB-sektor, och så vidare för varje post.

I den verkliga världen drabbar en sådan påföljd Samsung EVO SSD, för vilken ashift=13, men dessa SSD-enheter ljuger om sin sektorstorlek, och därför är standardinställningen inställd på ashift=9. Om en erfaren systemadministratör inte ändrar denna inställning, fungerar denna SSD långsammare konventionell magnetisk hårddisk.

Som jämförelse, för för stor storlek ashift det finns praktiskt taget inga straff. Det finns ingen verklig prestationsstraff, och ökningen av oanvänt utrymme är oändligt liten (eller noll med komprimering aktiverad). Därför rekommenderar vi starkt att även de enheter som använder 512-byte sektorer installeras ashift=12 eller ashift=13att möta framtiden med tillförsikt.

Fast egendom ashift är inställd för varje virtuell vdev-enhet, och inte för poolen, som många felaktigt tror - och ändras inte efter installationen. Om du råkar slå ashift när du lägger till en ny vdev till en pool har du oåterkalleligt förorenat poolen med en lågpresterande enhet och det finns vanligtvis inget annat val än att förstöra poolen och börja om. Även om du tar bort vdev kommer du inte att rädda dig från en trasig konfiguration ashift!

Kopiera-på-skriv-mekanism

ZFS Basics: Lagring och prestanda
Om ett vanligt filsystem behöver skriva över data ändrar det varje block där det är

ZFS Basics: Lagring och prestanda
Ett kopiera-på-skriv-filsystem skriver en ny blockversion och låser sedan upp den gamla versionen

ZFS Basics: Lagring och prestanda
Sammanfattningsvis, om vi ignorerar den faktiska fysiska platsen för blocken, så förenklas vår "datakomet" till en "datamask" som rör sig från vänster till höger över kartan över tillgängligt utrymme

ZFS Basics: Lagring och prestanda
Nu kan vi få en god uppfattning om hur kopiera-på-skriv-ögonblicksbilder fungerar - varje block kan tillhöra flera ögonblicksbilder och kommer att kvarstå tills alla associerade ögonblicksbilder förstörs

Mekanismen Copy on Write (CoW) är den grundläggande grunden för det som gör ZFS till ett så fantastiskt system. Grundkonceptet är enkelt - om du ber ett traditionellt filsystem att ändra en fil kommer det att göra precis vad du bad om. Om du ber ett kopiera-på-skriv-filsystem att göra detsamma, kommer det att säga "ok" men ljug för dig.

Istället skriver ett kopiera-på-skriv-filsystem en ny version av det modifierade blocket och uppdaterar sedan filens metadata för att koppla bort det gamla blocket och associera det nya blocket du just skrev till det.

Att ta bort det gamla blocket och länka det nya görs i en operation, så det kan inte avbrytas - om du stänger av efter detta har du en ny version av filen, och om du stänger av tidigt har du den gamla versionen . I vilket fall som helst kommer det inte att finnas några konflikter i filsystemet.

Copy-on-write i ZFS sker inte bara på filsystemnivå, utan också på diskhanteringsnivå. Detta betyder att ZFS inte påverkas av blanksteg (ett hål i RAID) - ett fenomen när remsan bara hunnit spela in delvis innan systemet kraschade, med arrayskada efter en omstart. Här är randen skriven atomiskt, vdev är alltid sekventiell, och Bob är din farbror.

ZIL: ZFS avsiktslogg

ZFS Basics: Lagring och prestanda
ZFS-systemet behandlar synkrona skrivningar på ett speciellt sätt - det lagrar dem tillfälligt men omedelbart i ZIL innan de skrivs permanent senare tillsammans med asynkrona skrivningar.

ZFS Basics: Lagring och prestanda
Vanligtvis läses data som skrivs till en ZIL aldrig igen. Men det är möjligt efter en systemkrasch

ZFS Basics: Lagring och prestanda
SLOG, eller sekundär LOG-enhet, är bara en speciell - och helst mycket snabb - vdev, där ZIL kan lagras separat från huvudminnet

ZFS Basics: Lagring och prestanda
Efter en krasch spelas all smutsig data i ZIL upp igen - i det här fallet är ZIL på SLOG, så det spelas upp därifrån

Det finns två huvudkategorier av skrivoperationer - synkron (synk) och asynkron (asynkron). För de flesta arbetsbelastningar är de allra flesta skrivningar asynkrona - filsystemet gör att de kan aggregeras och utfärdas i omgångar, vilket minskar fragmenteringen och ökar genomströmningen kraftigt.

Synkroniserade inspelningar är en helt annan sak. När en applikation begär en synkron skrivning säger den till filsystemet: "Du måste överföra detta till icke-flyktigt minne just nutills dess finns det inget annat jag kan göra." Därför bör synkrona skrivningar överföras till disken omedelbart - och om det ökar fragmenteringen eller minskar genomströmningen, så är det så.

ZFS hanterar synkrona skrivningar annorlunda än vanliga filsystem – istället för att omedelbart överlåta dem till vanlig lagring, överför ZFS dem till ett speciellt lagringsområde som kallas ZFS Intent Log, eller ZIL. Tricket är att dessa rekord också kvar i minnet, aggregeras tillsammans med normala asynkrona skrivbegäranden, för att senare spolas till lagringen som helt normala TXG:er (transaktionsgrupper).

I normal drift skrivs ZIL till och läses aldrig igen. När posterna från ZIL efter några ögonblick committeras till huvudminnet i vanliga TXG:er från RAM, kopplas de bort från ZIL. Den enda gången något läses från ZIL är när poolen importeras.

Om ZFS misslyckas - ett operativsystem kraschar eller ett strömavbrott - medan det finns data i ZIL, kommer denna data att läsas under nästa poolimport (till exempel när nödsystemet startas om). Allt i ZIL kommer att läsas, grupperas i TXG:er, kopplas till huvudminnet och kopplas sedan loss från ZIL under importprocessen.

En av vdev-hjälparklasserna kallas LOG eller SLOG, den sekundära enheten i LOG. Den har ett syfte - att förse poolen med en separat, och helst mycket snabbare, mycket skrivbeständig vdev för att lagra ZIL, istället för att lagra ZIL i huvudvdev-lagringen. ZIL själv beter sig likadant oavsett var den är lagrad, men om LOG vdev har mycket hög skrivprestanda blir synkrona skrivningar snabbare.

Att lägga till en vdev med LOG till poolen fungerar inte kan inte förbättra asynkron skrivprestanda - även om du tvingar alla skrivningar till ZIL med zfs set sync=always, kommer de fortfarande att vara länkade till huvudlagringen i TXG på samma sätt och i samma takt som utan loggen. Den enda direkta prestandaförbättringen är fördröjningen av synkrona skrivningar (eftersom snabbare logg gör operationer snabbare). sync).

Men i en miljö som redan kräver många synkrona skrivningar, kan vdev LOG indirekt påskynda asynkrona skrivningar och icke-cachade läsningar. Att ladda ZIL-poster till en separat vdev LOG innebär mindre konflikter för IOPS på primär lagring, vilket förbättrar prestandan för alla läsningar och skrivningar i viss utsträckning.

Ögonblicksbilder

Kopiera-på-skriv-mekanismen är också en nödvändig grund för ZFS atomära ögonblicksbilder och inkrementell asynkron replikering. Det aktiva filsystemet har ett pekträd som markerar alla poster med aktuella data - när du tar en ögonblicksbild gör du helt enkelt en kopia av detta pekträd.

När en post skrivs över på det aktiva filsystemet, skriver ZFS först den nya blockversionen till oanvänt utrymme. Den kopplar sedan bort den gamla versionen av blocket från det nuvarande filsystemet. Men om någon ögonblicksbild hänvisar till det gamla blocket förblir det fortfarande oförändrat. Det gamla blocket kommer faktiskt inte att återställas som ledigt utrymme förrän alla ögonblicksbilder som refererar till detta block har förstörts!

Replikering

ZFS Basics: Lagring och prestanda
Mitt Steam-bibliotek 2015 var 158 GiB och inkluderade 126 927 filer. Detta är ganska nära den optimala situationen för rsync - ZFS-replikering över nätverket var "bara" 750 % snabbare.

ZFS Basics: Lagring och prestanda
I samma nätverk är det en helt annan historia att replikera en enda 40 GB Windows 7 virtuell maskinbildfil. ZFS-replikering är 289 gånger snabbare än rsync - eller "bara" 161 gånger snabbare om du är kunnig nog att anropa rsync med --inplace.

ZFS Basics: Lagring och prestanda
När en VM-bild skalas kommer rsync att skala med den. 1,9 TiB är inte så stor för en modern VM-bild - men den är tillräckligt stor för att ZFS-replikering är 1148 gånger snabbare än rsync, även med rsyncs --inplace-argument

När du väl förstår hur ögonblicksbilder fungerar borde det vara lätt att förstå kärnan i replikeringen. Eftersom en ögonblicksbild bara är ett träd av pekare till poster, följer det att om vi gör det zfs send ögonblicksbild, så skickar vi både detta träd och alla poster som är associerade med det. När vi skickar detta zfs send в zfs receive på målet skriver den både det faktiska innehållet i blocket och trädet av pekare som refererar till blocken till måldatauppsättningen.

Saker och ting blir ännu mer intressanta på andra sidan zfs send. Vi har nu två system som vart och ett innehåller poolname/datasetname@1, och du tar en ny ögonblicksbild poolname/datasetname@2. Därför, i den ursprungliga poolen du har datasetname@1 и datasetname@2, och i målpoolen hittills bara den första ögonblicksbilden datasetname@1.

Eftersom vi har en gemensam ögonblicksbild mellan källan och målet datasetname@1, vi kan göra det inkrementell zfs send över det. När vi säger till systemet zfs send -i poolname/datasetname@1 poolname/datasetname@2, den jämför två pekarträd. Alla pekare som bara finns i @2, hänvisar uppenbarligen till nya block - så vi behöver innehållet i dessa block.

På ett fjärrsystem bearbetar en inkrementell send lika enkelt. Först skriver vi alla nya poster som ingår i strömmen send, och lägg sedan till pekare till dessa block. Voila, det har vi @2 i det nya systemet!

ZFS asynkron inkrementell replikering är en enorm förbättring jämfört med tidigare icke-snapshot-baserade metoder som rsync. I båda fallen överförs endast ändrad data – men rsync måste först läsa från disken all data på båda sidor för att kontrollera summan och jämföra den. Däremot läser ZFS-replikering inget annat än pekarträd - och alla block som inte finns i den delade ögonblicksbilden.

Inbyggd kompression

Kopiera-på-skriv-mekanismen förenklar också inline-komprimeringssystemet. I ett traditionellt filsystem är komprimering problematiskt - både den gamla versionen och den nya versionen av den modifierade datan finns i samma utrymme.

Om vi ​​betraktar en bit data i mitten av en fil som börjar livet som en megabyte nollor från 0x00000000 och så vidare, är det väldigt enkelt att komprimera det till en sektor på disken. Men vad händer om vi ersätter den megabyten med nollor med en megabyte av inkomprimerbar data som JPEG eller pseudo-slumpmässigt brus? Oväntat kommer denna megabyte med data att kräva inte en, utan 256 4 KiB-sektorer, och på denna plats på disken är endast en sektor reserverad.

ZFS har inte detta problem, eftersom modifierade poster alltid skrivs till oanvänt utrymme - det ursprungliga blocket upptar bara en sektor på 4 KiB, och den nya posten kommer att uppta 256, men detta är inte ett problem - ett nyligen modifierat fragment från " mitten av filen skulle skrivas till oanvänt utrymme oavsett om dess storlek har ändrats eller inte, så för ZFS är detta en ganska vanlig situation.

Native ZFS-komprimering är inaktiverad som standard, och systemet erbjuder pluggbara algoritmer – för närvarande LZ4, gzip (1-9), LZJB och ZLE.

  • LZ4 är en strömningsalgoritm som erbjuder extremt snabb komprimering och dekompression och prestandafördelar för de flesta användningsfall - även på ganska långsamma processorer.
  • GZIP är en vördnadsvärd algoritm som alla Unix-användare känner till och älskar. Den kan implementeras med komprimeringsnivåer 1-9, med komprimeringsförhållande och CPU-användning som ökar när den närmar sig nivå 9. Algoritmen är väl lämpad för all text (eller andra mycket komprimerbara) användningsfall, men orsakar annars ofta CPU-problem − använd den med omsorg, särskilt på högre nivåer.
  • LZJB är den ursprungliga algoritmen i ZFS. Den är föråldrad och ska inte användas längre, LZ4 överträffar den på alla sätt.
  • DÅLIGT - nollnivåkodning, nollnivåkodning. Den berör inte normal data alls, utan komprimerar stora sekvenser av nollor. Användbar för helt inkomprimerbara datauppsättningar (som JPEG, MP4 eller andra redan komprimerade format) eftersom den ignorerar inkomprimerbar data men komprimerar oanvänt utrymme i de resulterande posterna.

Vi rekommenderar LZ4-komprimering för nästan alla användningsfall; prestationsstraffet när man möter inkompressibel data är mycket liten, och tillväxt prestanda för typiska data är betydande. Kopiera en virtuell maskinavbildning för en ny installation av Windows-operativsystemet (nyinstallerat OS, inga data inuti ännu) med compression=lz4 passerade 27% snabbare än med compression=noneI detta test 2015.

ARC - adaptiv ersättningscache

ZFS är det enda moderna filsystem vi känner till som använder sin egen läscachemekanism, snarare än att förlita sig på operativsystemets sidcache för att lagra kopior av nyligen lästa block i RAM.

Även om den ursprungliga cachen inte är utan problem - ZFS kan inte svara på nya minnesallokeringsförfrågningar lika snabbt som kärnan, så den nya utmaningen malloc() på minnesallokering kan misslyckas om den behöver det RAM som för närvarande är upptaget av ARC. Men det finns goda skäl att använda din egen cache, åtminstone för nu.

Alla kända moderna operativsystem, inklusive MacOS, Windows, Linux och BSD, använder LRU-algoritmen (Least Recently Used) för att implementera sidcachen. Detta är en primitiv algoritm som skjuter det cachade blocket "upp i kön" efter varje läsning, och skjuter blocken "ned i kön" efter behov för att lägga till nya cachemissar (block som borde ha lästs från disken, inte från cachen) upp.

Algoritmen fungerar vanligtvis bra, men på system med stora fungerande datamängder leder LRU lätt till trassling - att vräka ut ofta nödvändiga block för att ge plats åt block som aldrig kommer att läsas från cachen igen.

BÅGE är en mycket mindre naiv algoritm som kan ses som en "viktad" cache. Varje gång ett cachat block läses blir det lite "tyngre" och svårare att vräka - och även efter att ett block har vräkts spåras inom en viss tid. Ett block som har vräkts men sedan behöver läsas tillbaka i cachen blir också "tyngre".

Slutresultatet av allt detta är en cache med ett mycket högre träffförhållande, förhållandet mellan cacheträffar (läsningar utförda från cachen) och cachemissar (läser från disk). Detta är en extremt viktig statistik - inte bara är själva cacheträffarna storleksordningar snabbare, cachemissar kan också serveras snabbare, eftersom ju fler cacheträffar, desto färre samtidiga diskbegäranden och desto lägre latens för de återstående missarna som måste serveras med disk.

Slutsats

Efter att ha lärt oss den grundläggande semantiken för ZFS - hur kopiera-på-skriv fungerar, såväl som relationerna mellan lagringspooler, virtuella enheter, block, sektorer och filer - är vi redo att diskutera verkliga prestanda med reella siffror.

I nästa del kommer vi att ta en titt på den faktiska prestandan för pooler med speglade vdevs och RAIDz, gentemot varandra, och även kontra de traditionella Linux-kärnan RAID-topologier som vi har utforskat. tidigare.

Först ville vi bara täcka grunderna - själva ZFS-topologierna - men efteråt en sådan låt oss göra oss redo att prata om mer avancerad installation och inställning av ZFS, inklusive användningen av extra vdev-typer som L2ARC, SLOG och Special Allocation.

Källa: will.com

Lägg en kommentar