Grundlagen von ZFS: Speicher- und Leistungsmanagement

Grundlagen von ZFS: Speicher- und Leistungsmanagement

In diesem FrĂŒhling haben wir bereits einige EinfĂŒhrungsthemen besprochen, zum Beispiel, wie man die Geschwindigkeit Ihrer Laufwerke ĂŒberprĂŒft und was RAID ist. Im zweiten haben wir sogar versprochen, die Leistung verschiedener Multi-Disk-Topologien in ZFS weiter zu untersuchen. Dies ist ein Dateisystem der nĂ€chsten Generation, das jetzt ĂŒberall implementiert wird: von Apple bis Ubuntu.

Tja, heute ist der passendste Tag, um ZFS kennenzulernen, liebe Leser. Wissen Sie einfach, dass es nach einer bescheidenen EinschĂ€tzung des Entwicklers von OpenZFS, Matt Arents, „wirklich kompliziert ist“.

Aber bevor wir zu den Zahlen kommen – und die werden kommen, versprochen – zu allen Variationen der acht Laufwerk-Konfigurationen in ZFS, mĂŒssen wir ĂŒber das sprechen, als wie ZFS ĂŒberhaupt Daten auf der Festplatte speichert.

Zpool, vdev und device

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Dieses Diagramm eines vollstĂ€ndigen Pools umfasst drei unterstĂŒtzende vdevs, jeweils eine aus jeder Klasse, und vier fĂŒr RAIDz2

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Normalerweise gibt es keinen Grund, einen Pool aus nicht ĂŒbereinstimmenden Typen und GrĂ¶ĂŸen von vdevs zu erstellen – aber wenn Sie möchten, steht nichts dem im Weg.

Um das Dateisystem ZFS wirklich zu verstehen, muss man sich die tatsĂ€chliche Struktur genauer ansehen. Erstens kombiniert ZFS die traditionellen Ebenen der Volume- und Dateisystemverwaltung. Zweitens verwendet es einen transaktionalen Mechanismus fĂŒr das Copy-on-write. Diese Merkmale bedeuten, dass das System strukturell sehr anders ist als herkömmliche Dateisysteme und RAID-Arrays. Der erste Satz grundlegender Bausteine zum VerstĂ€ndnis: es ist der Speicherpool (zpool), das virtuelle GerĂ€t (vdev) und das reale GerĂ€t (device).

zpool

Der Speicherpool zpool ist die höchste Struktur in ZFS. Jeder Pool enthÀlt ein oder mehrere virtuelle GerÀte. Jedes davon enthÀlt wiederum ein oder mehrere reale GerÀte (device). Virtuelle Pools sind autarke Blöcke. Ein physischer Computer kann zwei oder mehr separate Pools enthalten, aber jeder ist völlig unabhÀngig von den anderen. Pools können keine virtuellen GerÀte gemeinsam nutzen.

Die Redundanz von ZFS befindet sich auf der Ebene der virtuellen GerĂ€te, nicht auf der Ebene der Pools. Auf der Ebene der Pools gibt es absolut keine Redundanz – wenn ein vdev-Laufwerk oder ein spezieller vdev verloren geht, geht der gesamte Pool mit ihm verloren.

Moderne Speicherpools können den Verlust des Caches oder des Journals des virtuellen GerĂ€ts ĂŒberstehen – obwohl sie möglicherweise eine kleine Menge an unsauberen Daten verlieren, wenn sie das vdev-Journal wĂ€hrend eines Stromausfalls oder Systemausfalls verlieren.

Es gibt ein weit verbreitetes MissverstĂ€ndnis, dass ZFS "Datenstreifen" (Stripes) ĂŒber den gesamten Pool geschrieben werden. Das ist nicht korrekt. Zpool ist keineswegs ein lustiger RAID0, es ist eher lustig JBOD mit einem komplexen variablen Verteilungssystem.

In der Regel werden die Aufzeichnungen entsprechend dem verfĂŒgbaren freien Speicherplatz auf die verfĂŒgbaren virtuellen GerĂ€te verteilt, sodass theoretisch alle gleichzeitig gefĂŒllt werden. In neueren Versionen von ZFS wird die aktuelle Nutzung (Auslastung) des vdev berĂŒcksichtigt – wenn ein virtuelles GerĂ€t signifikant stĂ€rker belastet ist als ein anderes (zum Beispiel aufgrund von LesevorgĂ€ngen), wird es vorĂŒbergehend fĂŒr SchreibvorgĂ€nge ĂŒbersprungen, obwohl der höchste Anteil an freiem Speicherplatz verfĂŒgbar ist.

Der Auslastungserkennungsmechanismus, der in moderne ZFS-Schreibverteilungsmethoden integriert ist, kann die Verzögerung verringern und die Bandbreite wĂ€hrend Zeiten ungewöhnlich hoher Last erhöhen – aber das ist kein Freibrief fĂŒr unbeabsichtigtes Mischen langsamer HDDs und schneller SSDs in einem Pool. Ein solch unausgewogener Pool wird dennoch mit der Geschwindigkeit des langsamsten GerĂ€ts arbeiten, als wĂ€re er ausschließlich aus solchen GerĂ€ten zusammengesetzt.

vdev

Jeder Speicherpool besteht aus einem oder mehreren virtuellen GerĂ€ten (virtual device, vdev). Jedes vdev umfasst wiederum ein oder mehrere physische GerĂ€te. Die meisten virtuellen GerĂ€te werden zur einfachen Datenspeicherung verwendet, es gibt jedoch mehrere unterstĂŒtzende vdev-Klassen, einschließlich CACHE, LOG und SPECIAL. Jeder dieser vdev-Typen kann eine der fĂŒnf Topologien haben: EinzelgerĂ€t (single-device), RAIDz1, RAIDz2, RAIDz3 oder Spiegel (mirror).

RAIDz1, RAIDz2 und RAIDz3 sind spezielle Varianten dessen, was Old-School-Nutzer als Double Parity RAID bezeichnen wĂŒrden. 1, 2 und 3 beziehen sich darauf, wie viele ParitĂ€tsblöcke fĂŒr jeden Datenstreifen zugewiesen sind. Anstelle von einzelnen Laufwerken zur Sicherstellung der ParitĂ€t verteilt RAIDz virtuelle GerĂ€te diese ParitĂ€t gleichmĂ€ĂŸig auf die Laufwerke. Ein RAIDz-Array kann so viele Laufwerke verlieren, wie es ParitĂ€tsblöcke hat; wenn es ein weiteres verliert, ist es ausgefallen und nimmt den Speicherpool mit sich.

In Spiegel-virtuellen GerĂ€ten (mirror vdev) wird jeder Block auf jedem GerĂ€t im vdev gespeichert. Obwohl die am hĂ€ufigsten verwendeten Spiegel doppelt sind (two-wide), kann ein Spiegel eine beliebige Anzahl von GerĂ€ten haben – in großen Installationen werden oft dreifache Spiegel verwendet, um die Leseleistung und Ausfallsicherheit zu erhöhen. Ein vdev-Spiegel kann jeden Ausfall ĂŒberstehen, solange mindestens ein GerĂ€t im vdev weiterhin funktioniert.

Einfache vdevs sind von Natur aus gefĂ€hrlich. Ein solches virtuelles GerĂ€t wird keinen Ausfall ĂŒberstehen – und wenn es als Speicher oder spezielles vdev verwendet wird, fĂŒhrt ein Ausfall zu einem Verlust des gesamten Pools. Seien Sie hier sehr, sehr vorsichtig.

Virtuelle GerĂ€te CACHE, LOG und SPECIAL können in einer beliebigen der oben genannten Topologien erstellt werden – aber denken Sie daran, dass der Verlust eines virtuellen GerĂ€ts SPECIAL den Verlust des Pools bedeutet, daher wird eine redundante Topologie dringend empfohlen.

GerÀt

Wahrscheinlich der einfachste zu verstehende Begriff in ZFS – es handelt sich um ein BlockgerĂ€t mit zufĂ€lligem Zugriff. Denken Sie daran, dass virtuelle GerĂ€te aus einzelnen GerĂ€ten bestehen und der Pool aus virtuellen GerĂ€ten besteht.

Festplatten – sowohl magnetische als auch SSDs – sind die am hĂ€ufigsten verwendeten BlockgerĂ€te, die als Bausteine fĂŒr vdevs eingesetzt werden. Allerdings ist jedes GerĂ€t, das einen Deskriptor in /dev hat, geeignet – sodass ganze Hardware-RAID-Arrays als einzelne GerĂ€te verwendet werden können.

Eine einfache Raw-Datei ist eines der wichtigsten alternativen BlockgerĂ€te, aus denen ein vdev aufgebaut werden kann. Testpools aus Sparse-Dateien sind eine sehr praktische Möglichkeit, um Poolbefehle zu testen und zu sehen, wie viel Speicher im Pool oder virtuellen GerĂ€t dieser Topologie verfĂŒgbar ist.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Sie können in nur wenigen Sekunden einen Testpool aus sparsen Dateien erstellen – vergessen Sie nicht, spĂ€ter den gesamten Pool und seine Komponenten zu löschen.

Angenommen, Sie möchten einen Server mit acht Festplatten einrichten und planen, 10 TB (~9300 GiB) Festplatten zu verwenden – aber Sie sind sich nicht sicher, welche Topologie am besten zu Ihren BedĂŒrfnissen passt. Im obigen Beispiel erstellen wir in nur wenigen Sekunden einen Testpool aus sparsen Dateien – und wissen nun, dass ein RAIDz2 vdev mit acht 10 TB Festplatten 50 TiB nutzbaren Speicherplatz bietet.

Eine weitere spezielle GerĂ€tekategorie sind SPARE (ErsatzgerĂ€te). Hot-Swap-fĂ€hige GerĂ€te gehören im Gegensatz zu herkömmlichen GerĂ€ten dem gesamten Pool und nicht einem einzelnen virtuellen GerĂ€t. Wenn ein vdev im Pool ausfĂ€llt und ein ErsatzgerĂ€t an den Pool angeschlossen und verfĂŒgbar ist, wird es automatisch dem betroffenen vdev zugeordnet.

Nachdem das ErsatzgerÀt mit dem betroffenen vdev verbunden ist, beginnt es, Datenkopien oder -rekonstruktionen zu erhalten, die auf dem fehlenden GerÀt vorhanden sein sollten. Im traditionellen RAID wird dies als Wiederherstellung (rebuilding) bezeichnet, wÀhrend es in ZFS "Wiederherstellung von Redundanz" (resilvering) genannt wird.

Es ist wichtig zu beachten, dass ErsatzgerĂ€te defekte GerĂ€te nicht dauerhaft ersetzen. Sie sind lediglich eine vorĂŒbergehende Lösung, um die Zeit zu verkĂŒrzen, wĂ€hrend ein vdev degradierbar ist. Nachdem der Administrator das ausgefallene GerĂ€t im vdev ersetzt hat, erfolgt die Wiedereinrichtung der Redundanz auf das permanente GerĂ€t, und das SPARE-GerĂ€t wird vom vdev getrennt und kehrt zu seiner Funktion als ErsatzgerĂ€t fĂŒr den gesamten Pool zurĂŒck.

DatensÀtze, Blöcke und Sektoren

Der nĂ€chste Baustein, den es auf unserer Reise durch ZFS zu verstehen gilt, bezieht sich weniger auf die Hardware als darauf, wie die Daten selbst organisiert und gespeichert werden. Wir ĂŒberspringen hier einige Ebenen – wie z.B. metaslab –, um es nicht mit Details zu ĂŒberfrachtet, wĂ€hrend wir das GesamtverstĂ€ndnis der Struktur bewahren.

Datensatz (dataset)

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Wenn wir zum ersten Mal einen Datensatz erstellen, zeigt er den gesamten verfĂŒgbaren Speicherplatz des Pools an. Dann setzen wir ein Kontingent fest – und Ă€ndern den EinhĂ€ngepunkt. Magie!

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Zvol ist grĂ¶ĂŸtenteils einfach ein Datensatz, der seiner Dateisystemschicht entledigt ist, die wir hier durch ein völlig normales Dateisystem wie ext4 ersetzen.

Der ZFS-Datensatz ist in etwa mit einem standardmĂ€ĂŸig montierten Dateisystem vergleichbar. Wie ein gewöhnliches Dateisystem scheint es auf den ersten Blick "einfach nur ein weiterer Ordner" zu sein. Doch genau wie bei herkömmlichen gemounteten Dateisystemen hat jeder ZFS-Datensatz seine eigenen grundlegenden Eigenschaften.

ZunĂ€chst kann einem Datensatz ein festgelegtes Kontingent zugewiesen werden. Wenn Sie zfs set quota=100G poolname/datasetname, dann können Sie nichts in den gemounteten Ordner schreiben /poolname/datasetname was ĂŒber 100 GiB hinausgeht.

Haben Sie die Anwesenheit – und Abwesenheit – der SchrĂ€gstriche zu Beginn jeder Zeile bemerkt? Jeder Datensatz hat seinen Platz sowohl in der ZFS-Hierarchie als auch in der Hierarchie des System-Mounts. In der ZFS-Hierarchie gibt es keinen fĂŒhrenden SchrĂ€gstrich – Sie beginnen mit dem Namen des Pools und dann dem Pfad von einem Datensatz zum nĂ€chsten. Zum Beispiel, pool/parent/child fĂŒr einen Datensatz mit dem Namen child unter dem ĂŒbergeordneten Datensatz parent in einem Pool mit dem kreativen Namen pool.

StandardmĂ€ĂŸig entspricht der Mountpunkt des Datensatzes seinem Namen in der ZFS-Hierarchie, mit einem SchrĂ€gstrich am Anfang – der Pool namens pool wird als /poolgemountet, der Datensatz parent wird in /pool/parentgemountet, und der untergeordnete Datensatz child wird in /pool/parent/childgemountet. Der systematische Mountpunkt des Datensatzes kann jedoch geĂ€ndert werden.

Wenn wir angeben, zfs set mountpoint=/lol pool/parent/child, dann wird der Datensatz pool/parent/child im System als /lol.

gemountet. Neben DatensĂ€tzen mĂŒssen wir auch Volumes (zvols) erwĂ€hnen. Ein Volume ist in etwa mit einem Datensatz vergleichbar, es gibt jedoch tatsĂ€chlich kein Dateisystem darin – es handelt sich einfach um ein BlockgerĂ€t. Sie können beispielsweise ein zvol mit dem Namen mypool/myzvol, dann es mit dem Dateisystem ext4 formatieren und dieses Dateisystem dann mounten – jetzt haben Sie ein ext4-Dateisystem, das alle Sicherheitsfunktionen von ZFS unterstĂŒtzt! Das mag auf einem Computer albern erscheinen, macht aber viel mehr Sinn als Backend bei der Exportierung eines iSCSI-GerĂ€ts.

Blöcke

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Eine Datei besteht aus einem oder mehreren Blöcken. Jeder Block wird auf einem virtuellen GerĂ€t gespeichert. Die BlockgrĂ¶ĂŸe entspricht normalerweise der Parameter recordsize, kann jedoch auf 2^ashiftreduziert werden, wenn er Metadaten oder eine kleine Datei enthĂ€lt.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Wir meinen wirklich, tatsÀchlich dass es einen enormen Leistungseinbruch gibt, wenn ashift zu klein eingestellt wird.

Im ZFS-Pool werden alle Daten, einschließlich Metadaten, in Blöcken gespeichert. Die maximale BlockgrĂ¶ĂŸe fĂŒr jedes Datenset wird in der Eigenschaft " recordsize (AufzeichnungsgrĂ¶ĂŸe) festgelegt. Die AufzeichnungsgrĂ¶ĂŸe kann variieren, beeinflusst jedoch nicht die GrĂ¶ĂŸe oder Position bereits in das Datenset geschriebenen Blöcke – sie gilt nur fĂŒr neue Blöcke beim Schreiben.

Sofern nicht anders festgelegt, betrĂ€gt die aktuelle StandardaufzeichnungsgrĂ¶ĂŸe 128 KiB. Dies ist eine Art schwieriger Kompromiss, bei dem die Leistung in den meisten FĂ€llen weder ideal noch schlimm sein wird. Recordsize kann auf einen beliebigen Wert von 4K bis 1M festgelegt werden (mit zusĂ€tzlichen Einstellungen recordsize kann es noch grĂ¶ĂŸer eingestellt werden, aber das ist selten eine gute Idee).

Jeder Block bezieht sich nur auf die Daten einer einzelnen Datei – Sie können nicht zwei verschiedene Dateien in einen Block stecken. Jede Datei besteht aus einem oder mehreren Blöcken, abhĂ€ngig von der GrĂ¶ĂŸe. Ist die DateigrĂ¶ĂŸe kleiner als die AufzeichnungsgrĂ¶ĂŸe, wird sie in einem kleineren Block gespeichert – zum Beispiel belegt ein 2 KiB großer Block mit einer Datei nur einen 4 KiB großen Sektor auf der Festplatte.

Ist die Datei groß genug und benötigt mehrere Blöcke, dann haben alle Aufzeichnungen mit dieser Datei die GrĂ¶ĂŸe recordsize – einschließlich der letzten Aufzeichnung, deren Hauptteil möglicherweise unbenutzter Speicherplatz ist..

Volumes vom Typ zvol haben keine Eigenschaft recordsize – stattdessen haben sie eine Ă€quivalente Eigenschaft volblocksize.

Sektoren

Der letzte, grundlegendste Baustein – der Sektor. Dies ist die kleinste physikalische Einheit, die von dem zugrunde liegenden GerĂ€t geschrieben oder gelesen werden kann. Jahrzehntelang wurden in den meisten Festplatten Sektoren mit 512 Bytes verwendet. In letzter Zeit sind die meisten Festplatten auf 4 KiB-Sektoren eingestellt, und in einigen – insbesondere SSDs – sogar auf 8 KiB oder mehr.

Im ZFS-System gibt es eine Eigenschaft, die es ermöglicht, die SektorgrĂ¶ĂŸe manuell festzulegen. Diese Eigenschaft ashift. Es ist etwas verwirrend, dass ashift eine Potenz von zwei ist. Zum Beispiel ashift=9 bedeutet eine SektorgrĂ¶ĂŸe von 2^9 oder 512 Bytes.

ZFS fragt das Betriebssystem nach detaillierten Informationen zu jedem BlockgerĂ€t, wenn es in ein neues vdev hinzugefĂŒgt wird, und stellt theoretisch automatisch den ashift entsprechend diesen Informationen ein. Leider lĂŒgen viele Festplatten ĂŒber ihre SektorgrĂ¶ĂŸe, um die KompatibilitĂ€t mit Windows XP zu wahren (das nicht in der Lage war, Festplatten mit anderen SektorgrĂ¶ĂŸen zu erkennen).

Das bedeutet, dass es fĂŒr den ZFS-Administrator dringend empfohlen wird, die tatsĂ€chliche SektorgrĂ¶ĂŸe seiner GerĂ€te zu kennen und manuell einzustellen ashift. Wenn ein zu kleiner ashift eingestellt ist, steigt die Anzahl der Lese-/Schreiboperationen astronomisch an. So bedeutet das Schreiben von 512-Byte-"Sektoren" in einen tatsĂ€chlichen Sektor von 4 KiB, dass zuerst der erste "Sektor" geschrieben, dann der 4 KiB-Sektor gelesen, dieser mit dem zweiten 512-Byte-"Sektor" geĂ€ndert und dann zurĂŒck in den neuen 4 KiB-Sektor geschrieben werden muss, und so weiter fĂŒr jede Aufzeichnung.

In der realen Welt hat dieser Strafen einen großen Einfluss auf die Samsung EVO Solid-State-Laufwerke, fĂŒr die gelten muss ashift=13, aber diese SSDs lĂŒgen ĂŒber ihre SektorgrĂ¶ĂŸe, weshalb standardmĂ€ĂŸig eingestellt wird ashift=9. Wenn ein erfahrener Systemadministrator diesen Parameter nicht Ă€ndert, arbeitet diese SSD , als Muster, die verwenden wie eine herkömmliche magnetische HDD.

Im Vergleich dazu gibt es bei einer zu großen GrĂ¶ĂŸe ashift praktisch keinen Nachteil. Es gibt keinen echten Leistungsabfall, und der Anstieg des nicht genutzten Raums ist unendlich gering (oder null, wenn die Kompression aktiviert ist). Daher empfehlen wir nachdrĂŒcklich sogar fĂŒr Festplatten, die tatsĂ€chlich 512-Byte-Sektoren verwenden, einzustellen ashift=12 oder sogar ashift=13, um sicher in die Zukunft zu blicken.

Eigenschaft ashift wird fĂŒr jedes virtuelle GerĂ€t vdev eingestellt, und nicht fĂŒr den Pool, wie viele fĂ€lschlicherweise denken – und wird nach der Einstellung nicht mehr geĂ€ndert. Wenn Sie versehentlich ashift beim HinzufĂŒgen eines neuen vdevs zum Pool durcheinandergebracht haben, haben Sie diesen Pool unwiderruflich mit einem GerĂ€t mit niedriger Leistung verschmutzt, und in der Regel gibt es keinen anderen Ausweg, als den Pool zu löschen und von vorne zu beginnen. Selbst das Entfernen des vdev wird die falsche Konfiguration nicht retten. ashift!

Der Mechanismus des Schreibens

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Wenn ein normales Dateisystem Daten neu schreiben muss, Àndert es jeden Block dort, wo er sich befindet.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Das Dateisystem mit Copy-on-Write schreibt eine neue Version des Blocks und entsperrt dann die alte Version.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
In abstrakter Form, wenn wir die tatsĂ€chliche physische Anordnung der Blöcke ignorieren, vereinfacht sich unser „Datenkomet“ zu einem „Datenwurm“, der sich von links nach rechts ĂŒber die verfĂŒgbare Speicherkarte bewegt.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Jetzt können wir uns ein gutes Bild davon machen, wie Snapshots mit Copy-on-Write funktionieren – jeder Block kann mehreren Snapshots angehören und bleibt bestehen, bis alle zugehörigen Snapshots gelöscht werden.

Der Mechanismus Copy-on-Write (CoW) ist das grundlegende Prinzip, das ZFS zu einem so erstaunlichen System macht. Das Hauptkonzept ist einfach – wenn Sie ein traditionelles Dateisystem bitten, eine Datei zu Ă€ndern, wird es genau das tun, was Sie verlangen. Wenn Sie ein Copy-on-Write-Dateisystem dasselbe bitten, wird es sagen: „In Ordnung“ – aber es wird Sie anlĂŒgen.

Stattdessen schreibt das Copy-on-Write-Dateisystem eine neue Version des geÀnderten Blocks und aktualisiert die Metadaten der Datei, sodass die Verbindung zum alten Block getrennt und mit dem neuen Block, den Sie gerade geschrieben haben, verbunden wird.

Das Trennen des alten Blocks und das VerknĂŒpfen des neuen Blocks erfolgt in einem einzigen Schritt, sodass es nicht unterbrochen werden kann – wenn Sie die Stromversorgung nach diesem Vorgang zurĂŒcksetzen, erhalten Sie die neue Version der Datei, und wenn Sie die Stromversorgung vorher zurĂŒcksetzen, haben Sie die alte Version. In jedem Fall treten im Dateisystem keine Konflikte auf.

Copy-on-Write in ZFS geschieht nicht nur auf Dateisystemebene, sondern auch auf der Ebene des Festplattenspeichers. Das bedeutet, dass ZFS nicht anfĂ€llig fĂŒr das Schreibloch ist (Schreibloch im RAID) – ein PhĂ€nomen, bei dem ein Stripe nur teilweise geschrieben werden konnte, bevor das System ausfiel, was zu einem beschĂ€digten Array nach dem Neustart fĂŒhrt. Hier wird Stripe atomar geschrieben, vdev ist immer konsistent, und Bob ist dein Onkel..

ZIL: ZFS Intent Log

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Das ZFS-System behandelt synchrone SchreibvorgĂ€nge auf besondere Weise – es speichert sie vorĂŒbergehend, aber sofort im ZIL, bevor es sie spĂ€ter zusammen mit asynchronen SchreibvorgĂ€ngen dauerhaft speichert.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
In der Regel werden die im ZIL geschriebenen Daten nie wieder gelesen. Aber das ist nach einem Systemausfall möglich.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
SLOG, oder ein sekundĂ€res LOG-GerĂ€t, ist einfach ein spezieller – idealerweise sehr schneller – vdev, wo ZIL getrennt vom Hauptspeicher aufbewahrt werden kann.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Nach einem Ausfall werden alle schmutzigen Daten im ZIL wiederhergestellt – in diesem Fall befindet sich der ZIL auf dem SLOG, sodass sie genau von dort wiederhergestellt werden.

Es gibt zwei Hauptkategorien von Schreiboperationen – synchrone (sync) und asynchrone (async). FĂŒr die meisten Arbeitslasten sind ĂŒberwiegend mehr als 90 % der Schreiboperationen asynchron – das Dateisystem ermöglicht es, sie zu aggregieren und in Paketen auszugeben, was die Fragmentierung verringert und die Durchsatzrate erheblich steigert.

Synchrone SchreibvorgĂ€nge sind eine ganz andere Angelegenheit. Wenn eine Anwendung eine synchrone Speicherung anfordert, sagt sie dem Dateisystem: „Du musst das in nichtflĂŒchtigem Speicher festhalten, jetzt gleich, und bis dahin kann ich nichts anderes tun.“ Daher mĂŒssen synchrone SchreibvorgĂ€nge sofort auf der Festplatte festgeschrieben werden – und wenn das die Fragmentierung erhöht oder die Durchsatzrate verringert, ist das eben so.

ZFS behandelt synchrone SchreibvorgĂ€nge anders als herkömmliche Dateisysteme – anstatt sie sofort in den Standard-Speicher zu schreiben, speichert ZFS sie in einem speziellen Speicherbereich, der als ZFS Intent Log (ZIL) bezeichnet wird. Der Clou dabei ist, dass diese EintrĂ€ge auch im Speicher aggregiert bleiben, zusammen mit den normalen asynchronen Schreibanfragen, um spĂ€ter als ganz normale TXG (Transaction Groups, Transaktionsgruppen) ins SpeichergerĂ€t geschrieben zu werden.

Im normalen Betrieb wird ZIL geschrieben und danach nie wieder gelesen. Wenn nach einigen Momenten die EintrĂ€ge aus dem ZIL im Hauptspeicher in den ĂŒblichen TXG gespeichert werden, werden sie vom ZIL getrennt. Das einzige Mal, dass etwas aus dem ZIL gelesen wird, ist beim Import eines Pools.

Wenn es zu einem ZFS-Ausfall kommt – sei es ein Betriebssystemabsturz oder ein Stromausfall – wĂ€hrend sich Daten im ZIL befinden, werden diese Daten beim nĂ€chsten Import des Pools (z.B. beim Neustart des Absturzsystems) gelesen. Alles, was sich im ZIL befindet, wird gelesen, in TXG-Gruppen zusammengefĂŒhrt, im Hauptspeicher festgeschrieben und dann wĂ€hrend des Imports vom ZIL getrennt.

Eine der Hilfsklassen vdev nennt sich LOG oder SLOG, das sekundĂ€re GerĂ€t LOG. Es hat eine einzige Aufgabe – einen Pool mit einem separaten und, vorzugsweise, viel schnelleren GerĂ€t vdev mit sehr hoher SchreibbestĂ€ndigkeit zum Speichern von ZIL bereitzustellen, anstelle von ZIL im Hauptspeicher vdev zu speichern. Das ZIL verhĂ€lt sich unabhĂ€ngig vom Speicherort gleich, aber wenn vdev mit LOG eine sehr hohe Schreibgeschwindigkeit hat, werden synchrone SchreibvorgĂ€nge schneller ausgefĂŒhrt.

Das HinzufĂŒgen von vdev mit LOG zum Pool kann die kann Leistung der asynchronen SchreibvorgĂ€nge nicht verbessern – selbst wenn Sie alle SchreibvorgĂ€nge in ZIL mithilfe von zfs set sync=alwayserzwingen, werden sie dennoch in demselben Maße an den Hauptspeicher in TXG gebunden, wie ohne Journal. Die einzige direkte Leistungsverbesserung ist die Verzögerung der synchronen SchreibvorgĂ€nge (da eine höhere Journalgeschwindigkeit die AusfĂŒhrung der VorgĂ€nge beschleunigt). sync).

In einer Umgebung, die bereits eine große Anzahl synchroner SchreibvorgĂ€nge benötigt, kann vdev LOG jedoch indirekt asynchrone SchreibvorgĂ€nge und nicht zwischengespeicherte LesevorgĂ€nge beschleunigen. Das Auslagern von ZIL-SchreibvorgĂ€ngen in ein separates vdev LOG bedeutet weniger Konkurrenz um IOPS im primĂ€ren Speicher, was die Leistung aller Lese- und SchreibvorgĂ€nge in gewissem Maße steigert.

Snapshots

Der Mechanismus der Schreibkopie ist auch eine notwendige Grundlage fĂŒr atomare Momentaufnahmen von ZFS und inkrementelle asynchrone Replikation. In einem aktiven Dateisystem gibt es einen Baum von Zeigern, der alle EintrĂ€ge mit den aktuellen Daten markiert – wenn Sie einen Snapshot erstellen, machen Sie einfach eine Kopie dieses Zeigerbaums.

Wenn ein Eintrag in einem aktiven Dateisystem ĂŒberschrieben wird, schreibt ZFS zuerst die neue Version des Blocks in nicht verwendeten Speicher. Anschließend trennt es die alte Version des Blocks vom aktuellen Dateisystem. Aber wenn irgendein Snapshot auf den alten Block verweist, bleibt er unverĂ€ndert. Der alte Block wird faktisch nicht als freier Speicher wiederhergestellt, bis alle Snapshots, die auf diesen Block verweisen, gelöscht werden!

Replikation

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Meine Steam-Bibliothek nahm im Jahr 2015 158 GiB in Anspruch und umfasste 126.927 Dateien. Das ist ziemlich nah an der optimalen Situation fĂŒr rsync – die ZFS-Replikation ĂŒber das Netzwerk war „nur“ um 750 % schneller.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Im selben Netzwerk ist die Replikation einer 40-Gigabyte-Image-Datei einer Windows 7-virtuellen Maschine eine ganz andere Geschichte. Die ZFS-Replikation erfolgt 289 Mal schneller als rsync – oder „nur“ 161 Mal schneller, wenn Sie genug Wissen haben, um rsync mit dem Parameter --inplace aufzurufen.

Grundlagen von ZFS: Speicher- und Leistungsmanagement
Wenn das Image der virtuellen Maschine skaliert wird, skalieren die Probleme von rsync ebenfalls mit. Die GrĂ¶ĂŸe von 1,9 TiB ist fĂŒr ein modernes Image einer virtuellen Maschine nicht besonders groß – aber sie ist groß genug, dass die ZFS-Replikation 1148 Mal schneller ist als rsync, selbst mit dem rsync-Argument --inplace.

Sobald Sie verstehen, wie Snapshots funktionieren, wird es einfach sein, das Wesen der Replikation zu erfassen. Da ein Snapshot lediglich einen Baum von Zeigern auf die DatensĂ€tze darstellt, folgt daraus, dass wenn wir einen zfs send Snapshot erstellen, wir diesen Baum sowie alle damit verbundenen DatensĂ€tze senden. Wenn wir dies ĂŒber zfs send in zfs receive auf das Zielobjekt ĂŒbertragen, schreibt es sowohl den tatsĂ€chlichen Blockinhalt als auch den Baum von Zeigern, die auf die Blöcke verweisen, in den Ziel-Datensatz.

Es wird noch interessanter beim zweiten zfs send. Jetzt haben wir zwei Systeme, von denen jedes poolname/datasetname@1enthĂ€lt, und Sie erstellen einen neuen Snapshot poolname/datasetname@2.Daher haben Sie im ursprĂŒnglichen Pool datasetname@1 und datasetname@2, wĂ€hrend im Zielpool vorerst nur der erste Snapshot vorhanden ist. datasetname@1.

Da wir einen gemeinsamen Snapshot zwischen Quelle und Ziel haben, können wir einen datasetname@1inkrementellen auf ihm durchfĂŒhren. Wenn wir zum System sagen zfs send zfs send -i poolname/datasetname@1 poolname/datasetname@2 , vergleicht es die beiden ZeigerbĂ€ume. Alle Zeiger, die nur in, verweisen offensichtlich auf neue Blöcke – daher benötigen wir den Inhalt dieser Blöcke. @2Im entfernten System ist die Verarbeitung der inkrementellen

ebenso einfach. Zuerst schreiben wir alle neuen DatensĂ€tze, die im Stream enthalten sind, send , und fĂŒgen dann die Zeiger auf diese Blöcke hinzu. VoilĂ , wir haben sendes im neuen System! @2 Asynchrone inkrementelle ZFS-Replikation ist eine enorme Verbesserung im Vergleich zu frĂŒheren Methoden, die nicht auf Snapshots basieren, wie rsync. In beiden FĂ€llen werden nur die geĂ€nderten Daten ĂŒbertragen – aber rsync muss zuerst

alle Daten von der Festplatte auf beiden Seiten lesen, um die Summe zu ĂŒberprĂŒfen und sie zu vergleichen. Im Gegensatz dazu liest die ZFS-Replikation nichts außer den ZeigerbĂ€umen – und allen Blöcken, die im gemeinsamen Snapshot nicht vorhanden sind. lesen Von der Festplatte werden alle Daten von beiden Seiten gelesen, um die Summe zu ĂŒberprĂŒfen und zu vergleichen. Im Gegensatz dazu liest die ZFS-Replikation nichts außer den ZeigerbĂ€umen – und beliebigen Blöcken, die nicht im gemeinsamen Snapshot enthalten sind.

Integrierte Kompression

Der Kopiermechanismus beim Schreiben vereinfacht auch das System der integrierten Kompression. In herkömmlichen Dateisystemen ist die Kompression problematisch – sowohl die alte Version als auch die neue Version der geĂ€nderten Daten befinden sich im selben Raum.

Wenn man einen Datenblock in der Mitte einer Datei betrachtet, der sein Leben als Megabyte an Nullen bei 0x00000000 beginnt und so weiter – lĂ€sst er sich sehr leicht auf einen Sektor auf der Festplatte komprimieren. Aber was passiert, wenn wir dieses Megabyte an Nullen durch ein Megabyte unkomprimierbarer Daten wie JPEG oder pseudorandomem Rauschen ersetzen? Überraschenderweise benötigt dieses Megabyte an Daten nicht einen, sondern 256 Sektoren von 4 KiB, wĂ€hrend an dieser Stelle auf der Festplatte nur ein Sektor reserviert ist.

ZFS hat dieses Problem nicht, da geĂ€nderte EintrĂ€ge immer in ungenutzten Raum geschrieben werden – der ursprĂŒngliche Block nimmt nur einen Sektor von 4 KiB ein, und der neue Eintrag benötigt 256, aber das ist kein Problem – der kĂŒrzlich geĂ€nderte Abschnitt aus der „Mitte“ der Datei wĂŒrde unabhĂ€ngig von den Änderungen seiner GrĂ¶ĂŸe in ungenutzten Raum geschrieben, daher ist dies fĂŒr ZFS eine ganz normale Situation.

Die integrierte Kompression von ZFS ist standardmĂ€ĂŸig deaktiviert, und das System bietet auswĂ€hlbare Algorithmen an – derzeit darunter LZ4, gzip (1-9), LZJB und ZLE.

  • LZ4 – ist ein Streaming-Algorithmus, der extrem schnelle Kompression und Dekompression bietet und Leistungsgewinne fĂŒr die meisten AnwendungsfĂ€lle ermöglicht – selbst auf relativ langsamen CPUs.
  • GZIP – ein angesehener Algorithmus, der von allen Benutzern von Unix-Systemen geschĂ€tzt wird. Er kann mit Kompressionsgraden von 1-9 umgesetzt werden, wobei die Kompression und die CPU-Nutzung mit AnnĂ€herung an Grad 9 steigen. Der Algorithmus eignet sich gut fĂŒr alle textbasierten (oder anderen extrem komprimierbaren) Anwendungen, kann jedoch in anderen FĂ€llen hĂ€ufig Probleme mit der CPU verursachen – verwenden Sie ihn vorsichtig, insbesondere auf höheren Stufen.
  • LZJB – der ursprĂŒngliche Algorithmus in ZFS. Er ist veraltet und sollte nicht mehr verwendet werden, LZ4 ĂŒbertrifft ihn in jeder Hinsicht.
  • ZLE — Zero-Level-Kodierung. Sie Ă€ndert im Allgemeinen normale Daten nicht, komprimiert jedoch große Nullfolgen. NĂŒtzlich fĂŒr vollstĂ€ndig nicht komprimierbare DatensĂ€tze (z. B. JPEG, MP4 oder andere bereits komprimierte Formate), da sie nicht komprimierbare Daten ignoriert, aber ungenutzten Speicherplatz in den endgĂŒltigen Aufzeichnungen komprimiert.

Wir empfehlen die LZ4-Kompression fĂŒr nahezu alle AnwendungsfĂ€lle; die Leistungseinbußen bei der Verarbeitung nicht komprimierbarer Daten sind minimal, und Zuwachs die Leistungssteigerung fĂŒr typische Daten ist erheblich. Das Kopieren eines Abbilds einer virtuellen Maschine fĂŒr eine neue Installation des Betriebssystems Windows (frisch installiertes OS, keine Daten sind bereits vorhanden) mit compression=lz4 verlief 27 % schneller als mit compression=none, in in diesem Test von 2015..

ARC — Adaptive Replacement Cache.

ZFS ist das einzige uns bekannte moderne Dateisystem, das einen eigenen Lese-Caching-Mechanismus verwendet und sich nicht auf den Betriebssystem-Seiten-Cache zur Speicherung von Kopien kĂŒrzlich gelesener Blöcke im RAM verlĂ€sst.

Obwohl der eigene Cache nicht ohne Probleme ist — ZFS kann nicht so schnell auf neue Anfragen zur Speicherzuweisung reagieren wie der Kernel, sodass ein neuer Aufruf malloc() zur Speicherzuteilung fehlschlagen kann, wenn er RAM benötigt, der derzeit vom ARC belegt ist. Aber es gibt gute GrĂŒnde, den eigenen Cache zu verwenden, zumindest jetzt.

Alle bekannten modernen Betriebssysteme, einschließlich MacOS, Windows, Linux und BSD, verwenden fĂŒr die Implementierung des Seiten-Caches den LRU-Algorithmus (Least Recently Used). Dies ist ein einfacher Algorithmus, der einen zwischengespeicherten Block nach jedem Lesen 'nach oben' in die Warteschlange verschiebt und 'nach unten' in der Warteschlange verdrĂ€ngt, wenn es notwendig ist, um neue Cache-Fehler (Blöcke, die von der Festplatte gelesen werden sollten und nicht aus dem Cache) nach oben hinzuzufĂŒgen.

Normalerweise funktioniert der Algorithmus gut, aber in Systemen mit großen ArbeitsdatensĂ€tzen fĂŒhrt LRU leicht zu Thrashing — die VerdrĂ€ngung hĂ€ufig benötigter Blöcke, um Platz fĂŒr Blöcke zu schaffen, die nie wieder aus dem Cache gelesen werden.

ARC — ein wesentlich weniger naiver Algorithmus, der als „gewichteter“ Cache betrachtet werden kann. Nach jedem Lesen eines zwischengespeicherten Blocks wird er etwas „schwerer“ und es wird schwieriger, ihn auszusondern – und selbst nach der Aussortierung wird der Block verfolgt fĂŒr einen bestimmten Zeitraum. Ein Block, der ausgesondert wurde, aber dann wieder in den Cache gelesen werden muss, wird ebenfalls „schwerer“.

Das Endergebnis all dessen ist ein Cache mit einem viel höheren TrefferverhĂ€ltnis – dem VerhĂ€ltnis zwischen Cache-Hits (Lesen, das aus dem Cache erfolgt) und Cache-Misses (Lesen von der Festplatte). Dies ist eine Ă€ußerst wichtige Statistik – zum einen werden die Cache-Hits um ein Vielfaches schneller bedient, zum anderen können die Cache-Misses ebenfalls schneller bedient werden, da je mehr Cache-Hits es gibt, desto weniger parallele Anfragen an die Festplatte gestellt werden und desto weniger Verzögerung fĂŒr die verbleibenden Misses, die von der Festplatte bedient werden mĂŒssen.

Fazit

Nachdem wir die grundlegende Semantik von ZFS untersucht haben – wie das Schreiben bei der Sicherung funktioniert sowie die Beziehungen zwischen Storage-Pools, virtuellen GerĂ€ten, Blöcken, Sektoren und Dateien – sind wir bereit, ĂŒber die tatsĂ€chliche Leistung mit echten Zahlen zu sprechen.

Im nÀchsten Abschnitt werden wir die tatsÀchliche Leistung von Spiegel-Pools mit vdev und RAIDz vergleichen, sowohl miteinander als auch im Vergleich zu traditionellen RAID-Topologien des Linux-Kernels, die wir untersucht haben. zuvor.

Zuerst wollten wir nur die Grundlagen – die ZFS-Topologien – betrachten, aber nach Versionen zu speichern?..) Schließlich speichern wir Versionen, damit wir sie spĂ€ter verwenden können, das heißt, um "zurĂŒckzuspringen", falls notwendig. werden wir bereit sein, ĂŒber eine fortgeschrittene Konfiguration und Feinabstimmung von ZFS zu sprechen, einschließlich der Verwendung von unterstĂŒtzenden Typen von vdev, wie L2ARC, SLOG und Spezialzuweisung.

Quelle: habr.com

60GB SSD 8Gb DDR4