ZFS Basics: opslag en prestaties

ZFS Basics: opslag en prestaties

Dit voorjaar hebben we al enkele inleidende onderwerpen besproken, bijvoorbeeld hoe u de snelheid van uw schijven kunt controleren и wat is RAID. In de tweede hebben we zelfs beloofd om door te gaan met het bestuderen van de prestaties van verschillende multi-disk-topologieën in ZFS. Dit is het bestandssysteem van de volgende generatie dat nu overal wordt geïmplementeerd: van Apple naar Ubuntu.

Nou, vandaag is de beste dag om kennis te maken met ZFS, nieuwsgierige lezers. Weet gewoon dat naar de bescheiden mening van OpenZFS-ontwikkelaar Matt Ahrens, "het echt moeilijk is".

Maar voordat we bij de cijfers komen - en dat zullen ze doen, dat beloof ik - voor alle opties voor een ZFS-configuratie met acht schijven, moeten we het hebben over hoe Over het algemeen slaat ZFS gegevens op schijf op.

Zpool, vdev en apparaat

ZFS Basics: opslag en prestaties
Dit volledige pooldiagram bevat drie extra vdev's, één voor elke klasse en vier voor RAIDz2

ZFS Basics: opslag en prestaties
Er is meestal geen reden om een ​​pool van niet-overeenkomende vdev-types en -groottes aan te maken - maar niets weerhoudt u ervan om dit te doen als u dat wilt.

Om het ZFS-bestandssysteem echt te begrijpen, moet u de werkelijke structuur ervan onder de loep nemen. Ten eerste verenigt ZFS de traditionele niveaus van volume- en bestandssysteembeheer. Ten tweede gebruikt het een transactioneel copy-on-write-mechanisme. Door deze kenmerken verschilt het systeem structureel sterk van conventionele bestandssystemen en RAID-arrays. De eerste set basisbouwstenen die u moet begrijpen, zijn de opslagpool (zpool), het virtuele apparaat (vdev) en het echte apparaat (apparaat).

zpool

De zpool-opslagpool is de bovenste ZFS-structuur. Elke pool bevat een of meer virtuele apparaten. Elk van hen bevat op zijn beurt een of meer echte apparaten (apparaat). Virtuele pools zijn op zichzelf staande blokken. Eén fysieke computer kan twee of meer afzonderlijke pools bevatten, maar elk is volledig onafhankelijk van de andere. Pools kunnen geen virtuele apparaten delen.

De redundantie van ZFS is op virtueel apparaatniveau, niet op poolniveau. Er is absoluut geen redundantie op poolniveau - als een drive vdev of speciale vdev verloren gaat, gaat de hele pool daarmee verloren.

Moderne opslagpools kunnen het verlies van een cache of een logboek van een virtueel apparaat overleven, hoewel ze een kleine hoeveelheid vuile gegevens kunnen verliezen als ze het vdev-logboek verliezen tijdens een stroomstoring of een systeemcrash.

Er is een algemene misvatting dat ZFS "datastrepen" over de hele pool worden geschreven. Dit is niet waar. Zpool is helemaal niet grappig RAID0, het is nogal grappig JBOD met een complex variabel distributiemechanisme.

De records worden grotendeels verdeeld over de beschikbare virtuele apparaten volgens de beschikbare vrije ruimte, dus in theorie zullen ze allemaal tegelijkertijd worden gevuld. In latere versies van ZFS wordt rekening gehouden met het huidige vdev-gebruik (gebruik) - als het ene virtuele apparaat aanzienlijk drukker is dan het andere (bijvoorbeeld vanwege leesbelasting), wordt het tijdelijk overgeslagen voor schrijven, ondanks dat het de hoogste vrije ruimte verhouding.

Het gebruiksdetectiemechanisme dat in moderne ZFS-schrijftoewijzingsmethoden is ingebouwd, kan latentie verminderen en de doorvoer verhogen tijdens periodes van ongewoon hoge belasting - maar dat is het niet carte blanche op onvrijwillige vermenging van langzame HDD's en snelle SSD's in één pool. Zo'n ongelijke pool zal nog steeds werken met de snelheid van het langzaamste apparaat, dat wil zeggen alsof het volledig uit dergelijke apparaten bestaat.

vdev

Elke opslagpool bestaat uit een of meer virtuele apparaten (virtual device, vdev). Elke vdev bevat op zijn beurt een of meer echte apparaten. De meeste virtuele apparaten worden gebruikt voor eenvoudige gegevensopslag, maar er zijn verschillende vdev-helperklassen, waaronder CACHE, LOG en SPECIAL. Elk van deze vdev-typen kan een van de vijf topologieën hebben: enkel apparaat (single-device), RAIDz1, RAIDz2, RAIDz3 of mirror (mirror).

RAIDz1, RAIDz2 en RAIDz3 zijn speciale varianten van wat de oldtimers double (diagonal) parity RAID zouden noemen. 1, 2 en 3 verwijzen naar hoeveel pariteitsblokken zijn toegewezen voor elke gegevensstrook. In plaats van afzonderlijke schijven voor pariteit, verdelen virtuele RAIDz-apparaten deze pariteit semi-gelijkmatig over schijven. Een RAIDz-array kan evenveel schijven verliezen als er pariteitsblokken zijn; als het er nog een verliest, crasht het en neemt het de opslagpool mee.

Bij gespiegelde virtuele apparaten (mirror vdev) wordt elk blok op elk apparaat in de vdev opgeslagen. Hoewel spiegels met twee brede spiegels het meest voorkomen, kan elk willekeurig aantal apparaten in een spiegel staan ​​- driedubbele spiegels worden vaak gebruikt in grote installaties voor verbeterde leesprestaties en fouttolerantie. Een vdev-spiegelserver kan elke storing overleven zolang ten minste één apparaat in de vdev blijft functioneren.

Enkele vdev's zijn inherent gevaarlijk. Zo'n virtueel apparaat overleeft geen enkele storing - en als het wordt gebruikt als opslag of een speciale vdev, zal het falen ervan leiden tot de vernietiging van de hele pool. Wees hier heel, heel voorzichtig.

CACHE, LOG en SPECIAL VA's kunnen worden gemaakt met behulp van een van de bovenstaande topologieën - maar vergeet niet dat het verlies van een SPECIAL VA het verlies van de pool betekent, dus een redundante topologie wordt ten zeerste aanbevolen.

apparaat

Dit is waarschijnlijk de gemakkelijkst te begrijpen term in ZFS - het is letterlijk een apparaat voor willekeurige toegang. Onthoud dat virtuele apparaten uit individuele apparaten bestaan, terwijl een pool uit virtuele apparaten bestaat.

Schijven - magnetisch of solid state - zijn de meest voorkomende blokapparaten die worden gebruikt als de bouwstenen van vdev. Elk apparaat met een descriptor in /dev is echter geschikt, dus volledige hardware-RAID-arrays kunnen als afzonderlijke apparaten worden gebruikt.

Een eenvoudig raw-bestand is een van de belangrijkste alternatieve blokapparaten waaruit een vdev kan worden opgebouwd. Testpools van schaarse bestanden is een zeer handige manier om poolopdrachten te controleren en te zien hoeveel ruimte beschikbaar is in een pool of virtueel apparaat van een bepaalde topologie.

ZFS Basics: opslag en prestaties
U kunt in slechts enkele seconden een testpool maken van schaarse bestanden - maar vergeet niet om daarna de hele pool en de bijbehorende componenten te verwijderen

Stel dat u een server op acht schijven wilt plaatsen en van plan bent schijven van 10 TB (~9300 GiB) te gebruiken, maar u weet niet zeker welke topologie het beste bij uw behoeften past. In het bovenstaande voorbeeld bouwen we binnen enkele seconden een testpool van schaarse bestanden - en nu weten we dat een RAIDz2 vdev van acht schijven van 10 TB 50 TiB aan bruikbare capaciteit biedt.

Een andere speciale klasse apparaten is SPARE (spare). Hot-swap-apparaten behoren, in tegenstelling tot gewone apparaten, tot de hele pool en niet tot een enkel virtueel apparaat. Als een vdev in de pool faalt en een reserve-apparaat is aangesloten op de pool en beschikbaar is, dan zal het automatisch lid worden van de getroffen vdev.

Na verbinding te hebben gemaakt met de getroffen vdev, begint het reserve-apparaat kopieën of reconstructies te ontvangen van de gegevens die op het ontbrekende apparaat zouden moeten staan. In traditionele RAID wordt dit rebuilding genoemd, terwijl het in ZFS resilvering wordt genoemd.

Het is belangrijk op te merken dat reserveapparaten defecte apparaten niet permanent vervangen. Dit is slechts een tijdelijke vervanging om de hoeveelheid tijd dat vdev gedegradeerd is te verminderen. Nadat de beheerder de defecte vdev heeft vervangen, wordt de redundantie op dat permanente apparaat hersteld en wordt SPARE losgekoppeld van de vdev en weer aan het werk gezet als reserve voor de hele pool.

Datasets, blokken en sectoren

De volgende reeks bouwstenen die we tijdens onze ZFS-reis moeten begrijpen, gaat minder over de hardware en meer over hoe de gegevens zelf zijn georganiseerd en opgeslagen. We slaan hier een paar niveaus over - zoals metaslab - om de details niet te vervuilen en tegelijkertijd de algehele structuur te begrijpen.

Dataset (dataset)

ZFS Basics: opslag en prestaties
Wanneer we voor het eerst een dataset maken, toont deze alle beschikbare poolruimte. Vervolgens stellen we het quotum in - en wijzigen we het koppelpunt. Magie!

ZFS Basics: opslag en prestaties
Zvol is voor het grootste deel slechts een dataset ontdaan van zijn bestandssysteemlaag, die we hier vervangen door een volkomen normaal ext4-bestandssysteem.

Een ZFS-dataset is ongeveer hetzelfde als een standaard aangekoppeld bestandssysteem. Net als een regulier bestandssysteem lijkt het op het eerste gezicht "gewoon een andere map". Maar net als gewone aankoppelbare bestandssystemen, heeft elke ZFS-dataset zijn eigen set basiseigenschappen.

Allereerst kan een dataset een toegewezen quotum hebben. Indien ingesteld zfs set quota=100G poolname/datasetname, dan kunt u niet naar de aangekoppelde map schrijven /poolname/datasetname meer dan 100 GB.

Let op de aanwezigheid - en afwezigheid - van schuine strepen aan het begin van elke regel? Elke dataset heeft zijn plaats in zowel de ZFS-hiërarchie als de systeemkoppelingshiërarchie. Er is geen leidende schuine streep in de ZFS-hiërarchie - u begint met de poolnaam en vervolgens het pad van de ene dataset naar de volgende. Bijvoorbeeld, pool/parent/child voor een dataset met de naam child onder de bovenliggende dataset parent in een zwembad met een creatieve naam pool.

Het koppelpunt van de dataset is standaard gelijk aan de naam in de ZFS-hiërarchie, met een schuine streep ervoor - de pool met de naam pool gemonteerd als /pool, dataset parent erin gemonteerd /pool/parenten de onderliggende dataset child erin gemonteerd /pool/parent/child. Het systeemkoppelpunt van de gegevensset kan echter worden gewijzigd.

Als we specificeren zfs set mountpoint=/lol pool/parent/child, dan de dataset pool/parent/child gemonteerd op het systeem als /lol.

Naast datasets moeten we volumes (zvols) noemen. Een volume is ongeveer hetzelfde als een dataset, behalve dat het eigenlijk geen bestandssysteem heeft - het is gewoon een blokapparaat. U kunt bijvoorbeeld creëren zvol Met naam mypool/myzvol, formatteer het vervolgens met een ext4-bestandssysteem en koppel dat bestandssysteem vervolgens aan - je hebt nu een ext4-bestandssysteem, maar met alle beveiligingsfuncties van ZFS! Dit lijkt misschien gek op een enkele machine, maar is veel logischer als backend bij het exporteren van een iSCSI-apparaat.

blokken

ZFS Basics: opslag en prestaties
Het bestand wordt vertegenwoordigd door een of meer blokken. Elk blok wordt opgeslagen op één virtueel apparaat. De blokgrootte is meestal gelijk aan de parameter recordgrootte, maar kan worden teruggebracht tot 2^dienstals het metadata of een klein bestand bevat.

ZFS Basics: opslag en prestaties
Wij echt echt geen grapje maken over de enorme prestatieboete als je een te kleine shift instelt

In een ZFS-pool wordt alle data, inclusief metadata, in blokken opgeslagen. De maximale blokgrootte voor elke dataset wordt gedefinieerd in de eigenschap recordsize (recordgrootte). De recordgrootte kan worden gewijzigd, maar dit verandert niets aan de grootte of locatie van blokken die al naar de dataset zijn geschreven - het heeft alleen invloed op nieuwe blokken terwijl ze worden geschreven.

Tenzij anders aangegeven, is de huidige standaard recordgrootte 128 KiB. Het is nogal een lastige afweging waarbij de prestaties niet perfect zijn, maar in de meeste gevallen ook niet verschrikkelijk. Recordsize kan worden ingesteld op elke waarde van 4K tot 1M (met geavanceerde instellingen recordsize u kunt er nog meer installeren, maar dit is zelden een goed idee).

Elk blok verwijst naar de gegevens van slechts één bestand - u kunt niet twee verschillende bestanden in één blok proppen. Elk bestand bestaat uit een of meer blokken, afhankelijk van de grootte. Als de bestandsgrootte kleiner is dan de recordgrootte, wordt het opgeslagen in een kleinere blokgrootte - een blok met een bestand van 2 KiB zal bijvoorbeeld slechts één sector van 4 KiB op de schijf innemen.

Als het bestand groot genoeg is en meerdere blokken nodig heeft, dan zullen alle records met dit bestand van grootte zijn recordsize - inclusief de laatste invoer, waarvan het grootste deel kan zijn ongebruikte ruimte.

zvols hebben geen eigendom recordsize - in plaats daarvan hebben ze een equivalente eigenschap volblocksize.

Sectoren

De laatste, meest basale bouwsteen is de sector. Het is de kleinste fysieke eenheid die kan worden geschreven naar of gelezen van het onderliggende apparaat. Decennia lang gebruikten de meeste schijven sectoren van 512 bytes. De laatste tijd zijn de meeste schijven geconfigureerd voor 4 KiB-sectoren, en sommige - vooral SSD's - hebben 8 KiB-sectoren of zelfs meer.

Het ZFS-systeem heeft een eigenschap waarmee u de sectorgrootte handmatig kunt instellen. Dit pand ashift. Enigszins verwarrend, ashift is een macht van twee. Bijvoorbeeld, ashift=9 betekent een sectorgrootte van 2^9 of 512 bytes.

ZFS vraagt ​​het besturingssysteem om gedetailleerde informatie over elk blokapparaat wanneer het wordt toegevoegd aan een nieuwe vdev, en installeert in theorie automatisch ashift correct op basis van die informatie. Helaas liegen veel schijven over hun sectorgrootte om de compatibiliteit met Windows XP te behouden (dat schijven met andere sectorgroottes niet kon begrijpen).

Dit betekent dat een ZFS-beheerder sterk wordt aangeraden om de werkelijke sectorgrootte van hun apparaten te kennen en deze handmatig in te stellen ashift. Als een shift te laag is ingesteld, dan neemt het aantal lees-/schrijfbewerkingen astronomisch toe. Dus, het schrijven van "sectoren" van 512 bytes naar een echte sector van 4 KiB betekent dat je de eerste "sector" moet schrijven, vervolgens de sector van 4 KiB moet lezen, deze moet wijzigen met een tweede "sector van 512 bytes", terugschrijven naar de nieuwe 4 KiB-sectoren, enz. voor elk item.

In de echte wereld treft zo'n boete Samsung EVO SSD's, waarvoor ashift=13, maar deze SSD's liegen over hun sectorgrootte en daarom is de standaard ingesteld op ashift=9. Verandert een ervaren systeembeheerder deze instelling niet, dan werkt deze SSD langzamer conventionele magnetische HDD.

Ter vergelijking, voor een te grote maat ashift er staat praktisch geen boete op. Er is geen echte prestatievermindering en de toename van ongebruikte ruimte is oneindig klein (of nul als compressie is ingeschakeld). Daarom raden we ten zeerste aan om zelfs die schijven te installeren die sectoren van 512 bytes gebruiken ashift=12 of ashift=13om de toekomst met vertrouwen tegemoet te treden.

Eigendom ashift is ingesteld voor elk vdev virtueel apparaat, en niet voor het zwembad, zoals velen ten onrechte denken - en verandert niet na installatie. Als je per ongeluk raakt ashift wanneer je een nieuwe vdev aan een pool toevoegt, heb je die pool onherstelbaar vervuild met een apparaat met lage prestaties en is er meestal geen andere keuze dan de pool te vernietigen en opnieuw te beginnen. Zelfs het verwijderen van vdev zal u niet redden van een kapotte configuratie ashift!

Copy-on-write-mechanisme

ZFS Basics: opslag en prestaties
Als een regulier bestandssysteem gegevens moet overschrijven, verandert het elk blok waar het zich bevindt

ZFS Basics: opslag en prestaties
Een copy-on-write bestandssysteem schrijft een nieuwe blokversie en ontgrendelt vervolgens de oude versie

ZFS Basics: opslag en prestaties
In abstracto, als we de daadwerkelijke fysieke locatie van de blokken negeren, wordt onze "datakomeet" vereenvoudigd tot een "dataworm" die van links naar rechts over de kaart met beschikbare ruimte beweegt

ZFS Basics: opslag en prestaties
Nu kunnen we een goed idee krijgen van hoe copy-on-write snapshots werken - elk blok kan tot meerdere snapshots behoren en blijft bestaan ​​totdat alle bijbehorende snapshots zijn vernietigd

Het Copy on Write (CoW) -mechanisme is de fundamentele basis van wat ZFS zo'n geweldig systeem maakt. Het basisconcept is eenvoudig: als je een traditioneel bestandssysteem vraagt ​​om een ​​bestand te wijzigen, zal het precies doen wat je vroeg. Als je een copy-on-write-bestandssysteem vraagt ​​om hetzelfde te doen, zal het "ok" zeggen, maar tegen je liegen.

In plaats daarvan schrijft een copy-on-write-bestandssysteem een ​​nieuwe versie van het gewijzigde blok en werkt vervolgens de metagegevens van het bestand bij om het oude blok te ontkoppelen en het nieuwe blok dat u zojuist hebt geschreven eraan te koppelen.

Het loskoppelen van het oude blok en het koppelen van het nieuwe gebeurt in één handeling, dus het kan niet worden onderbroken - als je daarna uitschakelt, heb je een nieuwe versie van het bestand, en als je voortijdig uitschakelt, heb je de oude versie . In ieder geval zullen er geen conflicten zijn in het bestandssysteem.

Copy-on-write in ZFS vindt niet alleen plaats op bestandssysteemniveau, maar ook op schijfbeheerniveau. Dit betekent dat ZFS niet wordt beïnvloed door witruimte (een gat in de RAID) - een fenomeen waarbij de strip tijd had om slechts gedeeltelijk op te nemen voordat het systeem crashte, met schade aan de array na opnieuw opstarten. Hier wordt de streep atomair geschreven, vdev is altijd opeenvolgend, en Bob is je oom.

ZIL: ZFS-intentielogboek

ZFS Basics: opslag en prestaties
Het ZFS-systeem behandelt synchrone schrijfbewerkingen op een speciale manier: het slaat ze tijdelijk maar onmiddellijk op in ZIL voordat ze ze later permanent samen met asynchrone schrijfbewerkingen wegschrijft.

ZFS Basics: opslag en prestaties
Doorgaans worden gegevens die naar een ZIL zijn geschreven nooit meer gelezen. Maar het is mogelijk na een systeemcrash

ZFS Basics: opslag en prestaties
SLOG, of secundair LOG device, is gewoon een speciale - en bij voorkeur zeer snelle - vdev, waar de ZIL apart van de hoofdopslag kan worden opgeslagen

ZFS Basics: opslag en prestaties
Na een crash worden alle vuile gegevens in ZIL opnieuw afgespeeld - in dit geval staat ZIL op SLOG, dus wordt het vanaf daar opnieuw afgespeeld

Er zijn twee hoofdcategorieën schrijfbewerkingen: synchroon (sync) en asynchroon (async). Voor de meeste workloads is de overgrote meerderheid van de schrijfbewerkingen asynchroon: dankzij het bestandssysteem kunnen ze worden geaggregeerd en in batches worden uitgegeven, waardoor fragmentatie wordt verminderd en de doorvoer aanzienlijk wordt verhoogd.

Gesynchroniseerde opnames zijn een heel andere zaak. Wanneer een applicatie om synchroon schrijven vraagt, vertelt het het bestandssysteem: "Je moet dit vastleggen in niet-vluchtig geheugen nu meteentot die tijd kan ik niets anders doen." Daarom moeten synchrone schrijfbewerkingen onmiddellijk naar de schijf worden vastgelegd - en als dat de fragmentatie vergroot of de doorvoer vermindert, dan is dat maar zo.

ZFS verwerkt synchrone schrijfbewerkingen anders dan gewone bestandssystemen: in plaats van ze onmiddellijk vast te leggen in reguliere opslag, legt ZFS ze vast in een speciaal opslaggebied dat het ZFS Intent Log of ZIL wordt genoemd. De truc is dat deze records ook blijven in het geheugen, worden samengevoegd met normale asynchrone schrijfverzoeken, om later als volkomen normale TXG's (Transaction Groups) naar de opslag te worden gespoeld.

Bij normaal gebruik wordt de ZIL geschreven en nooit meer gelezen. Wanneer na enkele ogenblikken de records van de ZIL zijn vastgelegd in de hoofdopslag in gewone TXG's van RAM, worden ze losgekoppeld van de ZIL. De enige keer dat er iets uit de ZIL wordt gelezen, is wanneer de pool wordt geïmporteerd.

Als ZFS faalt - een crash van het besturingssysteem of een stroomstoring - terwijl er gegevens in de ZIL staan, worden die gegevens gelezen tijdens de volgende poolimport (bijvoorbeeld wanneer het noodsysteem opnieuw wordt opgestart). Alles in de ZIL wordt gelezen, gegroepeerd in TXG's, toegewezen aan de hoofdopslag en vervolgens losgekoppeld van de ZIL tijdens het importproces.

Een van de vdev-helperklassen heet LOG of SLOG, het secundaire apparaat van LOG. Het heeft één doel - om de pool te voorzien van een aparte, en bij voorkeur veel snellere, zeer schrijfbestendige vdev om de ZIL op te slaan, in plaats van de ZIL op te slaan in de belangrijkste vdev-opslag. De ZIL zelf gedraagt ​​zich hetzelfde, ongeacht waar het is opgeslagen, maar als de LOG vdev zeer hoge schrijfprestaties heeft, zullen synchrone schrijfacties sneller zijn.

Het toevoegen van een vdev met LOG aan de pool werkt niet kan niet verbeter asynchrone schrijfprestaties - zelfs als u alle schrijfbewerkingen naar ZIL forceert met zfs set sync=always, zullen ze nog steeds op dezelfde manier en in hetzelfde tempo aan de hoofdopslag in TXG worden gekoppeld als zonder het logboek. De enige directe prestatieverbetering is de latentie van synchrone schrijfbewerkingen (omdat snellere logboekbewerkingen sneller verlopen). sync).

In een omgeving die echter al veel synchrone schrijfbewerkingen vereist, kan vdev LOG indirect asynchrone schrijfbewerkingen en niet-gecachete leesbewerkingen versnellen. Het offloaden van ZIL-vermeldingen naar een afzonderlijk vdev-LOG betekent minder strijd voor IOPS op primaire opslag, wat de prestaties van alle lees- en schrijfbewerkingen tot op zekere hoogte verbetert.

Momentopnamen

Het copy-on-write-mechanisme is ook een noodzakelijke basis voor ZFS atomic snapshots en incrementele asynchrone replicatie. Het actieve bestandssysteem heeft een pointerboom die alle records markeert met actuele gegevens - wanneer u een momentopname maakt, maakt u eenvoudig een kopie van deze pointerboom.

Wanneer een record op het actieve bestandssysteem wordt overschreven, schrijft ZFS eerst de nieuwe blokversie naar ongebruikte ruimte. Vervolgens wordt de oude versie van het blok losgekoppeld van het huidige bestandssysteem. Maar als een snapshot verwijst naar het oude blok, blijft het nog steeds ongewijzigd. Het oude blok zal niet echt worden hersteld als vrije ruimte totdat alle snapshots die verwijzen naar dit blok zijn vernietigd!

Replicatie

ZFS Basics: opslag en prestaties
Mijn Steam-bibliotheek in 2015 was 158 GiB en bevatte 126 bestanden. Dit komt vrij dicht in de buurt van de optimale situatie voor rsync - ZFS-replicatie via het netwerk was "slechts" 927% sneller.

ZFS Basics: opslag en prestaties
Op hetzelfde netwerk is het repliceren van een enkel imagebestand van een virtuele Windows 40-machine van 7 GB een heel ander verhaal. ZFS-replicatie is 289 keer sneller dan rsync - of "slechts" 161 keer sneller als je slim genoeg bent om rsync aan te roepen met --inplace.

ZFS Basics: opslag en prestaties
Wanneer een VM-image wordt geschaald, geeft rsync de schaal mee. 1,9 TiB is niet zo groot voor een moderne VM-image - maar het is groot genoeg dat ZFS-replicatie 1148 keer sneller is dan rsync, zelfs met het argument --inplace van rsync

Als u eenmaal begrijpt hoe snapshots werken, zou het gemakkelijk moeten zijn om de essentie van replicatie te begrijpen. Aangezien een momentopname slechts een boom is met verwijzingen naar records, volgt hieruit dat als we dat doen zfs send momentopname, dan sturen we zowel deze boom als alle bijbehorende records. Wanneer sturen we dit zfs send в zfs receive op het doel schrijft het zowel de daadwerkelijke inhoud van het blok als de boom van pointers die verwijzen naar de blokken naar de doeldataset.

Op de tweede wordt het nog interessanter zfs send. We hebben nu twee systemen, elk met poolname/datasetname@1en u maakt een nieuwe momentopname poolname/datasetname@2. Daarom heb je in de originele pool datasetname@1 и datasetname@2, en in de doelpool tot nu toe alleen de eerste momentopname datasetname@1.

Omdat we een gemeenschappelijke momentopname hebben tussen de bron en het doel datasetname@1, we kunnen het toenemend zfs send overheen. Als we tegen het systeem zeggen zfs send -i poolname/datasetname@1 poolname/datasetname@2, vergelijkt het twee aanwijzerbomen. Alle verwijzingen die alleen bestaan ​​in @2, verwijzen uiteraard naar nieuwe blokken - dus we hebben de inhoud van deze blokken nodig.

Op een extern systeem verwerkt een incrementeel send net zo eenvoudig. Eerst schrijven we alle nieuwe items die in de stream zijn opgenomen senden voeg vervolgens pointers toe aan die blokken. Voila, we hebben @2 in het nieuwe systeem!

ZFS asynchrone incrementele replicatie is een enorme verbetering ten opzichte van eerdere methoden die niet op snapshots zijn gebaseerd, zoals rsync. In beide gevallen worden alleen gewijzigde gegevens overgedragen - maar rsync moet eerst lezen van de schijf alle gegevens aan beide kanten om de som te controleren en te vergelijken. ZFS-replicatie leest daarentegen niets anders dan pointertrees - en alle blokken die niet aanwezig zijn in de gedeelde snapshot.

Ingebouwde compressie

Het copy-on-write-mechanisme vereenvoudigt ook het inline compressiesysteem. In een traditioneel bestandssysteem is compressie problematisch - zowel de oude versie als de nieuwe versie van de gewijzigde gegevens bevinden zich in dezelfde ruimte.

Als we een stukje data beschouwen in het midden van een bestand dat begint als een megabyte van nullen vanaf 0x00000000 enzovoort, is het heel gemakkelijk om het te comprimeren tot één sector op schijf. Maar wat gebeurt er als we die megabyte aan nullen vervangen door een megabyte aan onsamendrukbare gegevens zoals JPEG of pseudo-willekeurige ruis? Onverwachts vereist deze megabyte aan gegevens niet één, maar 256 4 KiB-sectoren, en op deze plaats op de schijf is slechts één sector gereserveerd.

ZFS heeft dit probleem niet, omdat gewijzigde records altijd naar ongebruikte ruimte worden geschreven - het originele blok neemt slechts één sector van 4 KiB in beslag en het nieuwe record zal er 256 in beslag nemen, maar dit is geen probleem - een recent gewijzigd fragment uit de " middle" van het bestand zou naar ongebruikte ruimte worden geschreven, ongeacht of de grootte is veranderd of niet, dus voor ZFS is dit een vrij normale situatie.

Native ZFS-compressie is standaard uitgeschakeld en het systeem biedt inplugbare algoritmen, momenteel LZ4, gzip (1-9), LZJB en ZLE.

  • LZ4 is een streaming-algoritme dat extreem snelle compressie en decompressie en prestatievoordelen biedt voor de meeste gebruikssituaties - zelfs op vrij trage CPU's.
  • GZIP is een eerbiedwaardig algoritme dat alle Unix-gebruikers kennen en waarderen. Het kan worden geïmplementeerd met compressieniveaus 1-9, waarbij de compressieverhouding en het CPU-gebruik toenemen naarmate het niveau 9 nadert. Het algoritme is zeer geschikt voor alle tekst (of andere zeer comprimeerbare) use-cases, maar veroorzaakt verder vaak CPU-problemen - gebruik het met zorg, vooral op hogere niveaus.
  • LZJB is het originele algoritme in ZFS. Hij is achterhaald en mag niet meer gebruikt worden, de LZ4 overtreft hem in alle opzichten.
  • FOUT - codering op nulniveau, codering op nulniveau. Het raakt de normale gegevens helemaal niet, maar comprimeert grote reeksen nullen. Nuttig voor volledig oncomprimeerbare datasets (zoals JPEG, MP4 of andere reeds gecomprimeerde formaten) omdat het oncomprimeerbare data negeert maar ongebruikte ruimte in de resulterende records comprimeert.

We raden LZ4-compressie aan voor bijna alle use-cases; de prestatievermindering bij het tegenkomen van onsamendrukbare gegevens is erg klein, en groei prestaties voor typische gegevens zijn aanzienlijk. Een image van een virtuele machine kopiëren voor een nieuwe installatie van het Windows-besturingssysteem (nieuw geïnstalleerd besturingssysteem, nog geen gegevens erin) met compression=lz4 27% sneller geslaagd dan met compression=noneIn deze toets in 2015.

ARC - adaptieve vervangende cache

ZFS is het enige moderne bestandssysteem dat we kennen dat zijn eigen leescachemechanisme gebruikt, in plaats van te vertrouwen op de paginacache van het besturingssysteem om kopieën van recent gelezen blokken in RAM op te slaan.

Hoewel de native cache niet zonder problemen is, kan ZFS niet zo snel reageren op nieuwe geheugentoewijzingsverzoeken als de kernel, dus de nieuwe uitdaging malloc() op geheugentoewijzing kan mislukken als het de RAM nodig heeft die momenteel wordt gebruikt door ARC. Maar er zijn goede redenen om je eigen cache te gebruiken, althans voorlopig.

Alle bekende moderne besturingssystemen, waaronder MacOS, Windows, Linux en BSD, gebruiken het LRU-algoritme (Least Recent Used) om de paginacache te implementeren. Dit is een primitief algoritme dat het in de cache opgeslagen blok na elke lezing "naar boven in de wachtrij" duwt, en de blokken naar behoefte "naar beneden in de wachtrij" duwt om nieuwe cache-missers toe te voegen (blokken die van de schijf hadden moeten worden gelezen, niet uit de cache). omhoog.

Het algoritme werkt meestal prima, maar op systemen met grote werkende datasets leidt LRU gemakkelijk tot thrashing - het verwijderen van veelgebruikte blokken om ruimte te maken voor blokken die nooit meer uit de cache zullen worden gelezen.

ARC is een veel minder naïef algoritme dat kan worden gezien als een "gewogen" cache. Elke keer dat een blok in de cache wordt gelezen, wordt het een beetje "zwaarder" en moeilijker te verwijderen - en zelfs na het verwijderen van een blok gevolgd binnen een bepaalde tijd. Een blok dat is verwijderd maar vervolgens moet worden teruggelezen in de cache, wordt ook "zwaarder".

Het eindresultaat van dit alles is een cache met een veel hogere hitratio, de verhouding tussen cachehits (leesbewerkingen uitgevoerd vanuit de cache) en cachemissers (leesbewerkingen van schijf). Dit is een uiterst belangrijke statistiek - niet alleen worden de cachetreffers zelf veel sneller afgehandeld, cachemissers kunnen ook sneller worden verwerkt, aangezien hoe meer cachehits, hoe minder gelijktijdige schijfverzoeken en hoe lager de latentie voor de resterende missers die moeten worden verwerkt. worden geserveerd met schijf.

Conclusie

Nadat we de basissemantiek van ZFS hebben geleerd - hoe copy-on-write werkt, evenals de relaties tussen opslagpools, virtuele apparaten, blokken, sectoren en bestanden - zijn we klaar om real-world prestaties met echte cijfers te bespreken.

In het volgende deel zullen we kijken naar de daadwerkelijke prestaties van pools met gespiegelde vdev's en RAIDz, ten opzichte van elkaar, en ook ten opzichte van de traditionele Linux-kernel RAID-topologieën die we hebben onderzocht. vroeger.

In eerste instantie wilden we alleen de basis behandelen - de ZFS-topologieën zelf - maar daarna zo een laten we ons klaarmaken om te praten over meer geavanceerde setup en tuning van ZFS, inclusief het gebruik van hulp-vdev-typen zoals L2ARC, SLOG en Special Allocation.

Bron: www.habr.com

Voeg een reactie