ZFS auf Linux/ Wie ZFS Daten ablegt

Wie ZFS Daten ablegt Bearbeiten

Im folgenden sind Begriffe erklärt und Algorithmen angedeutet, damit man versteht, wie ZFS Dateien auf die Platten schreibt und von diesen liest. Dieses Verständnis erleichtert das Tuning, die Dimensionierung der Hardware, die Wahl von Parametern, das Lesen von Dokumentationen, ...


Sektoren Bearbeiten

Ein Sektor bezeichnet bei Festplatten die kleinste Organisationseinheit, die gelesen bzw. geschrieben werden kann.

Zu beachten ist, dass moderne Festplatten das Advanced Format (AF) nutzen. Dabei haben die Sektoren eine Größe von 4 KiB statt der ursprünglichen 512 Byte Advanced_Format . Zusätzlich führen diese Festplatten meist eine Emulation von 512 Byte Sektoren durch, um auch mit älteren Betriebssystemen kompatibel zu bleiben. Durch die Anpassung der Blockgröße an die Sektorgröße können überflüssige Lese- und Schreibzugriffe vermieden und somit eine Steigerung der Geschwindigkeit erreicht werden. Werden Festplatten mit AF eingesetzt, sollte die Anpassung immer an die physische Sektorgröße von 4 KiB und nicht an die emulierte Größe erfolgen.


physische Blocks Bearbeiten

  • Die Daten in einem physischen Block versucht ZFS in einen Sektor eines vdevs zu schreiben, was meist eine Platte ist. Lesen analog.
  • Die physische Blockgröße wird durch den Pool-Parameter ashift festgelegt mit Hilfe des Befehls zpool.
  • Die physische Blockgröße wird immer für ein bestimmtes vdev definiert: beim Erstellen eines Pools oder beim Hinzufügen eines vdevs. Sobald diese Größe für einen Pool definiert ist, kann die Blockgröße nicht mehr verändert werden - außer durch Zerstörung des Pools. Aufgrund der Endgültigkeit des Wertes ist es wichtig, sich vor der Erstellung des Pools Gedanken über die richtige Blockgröße, zu machen.
  • Bei der Verwendung von Festplatten sollte die Blockgröße immer gleich der Größe der Sektoren sein.
  • Ein Pool kann aus vdevs mit verschiedenen Blockgrößen aufgebaut werden.
  • Bei moderner Hardware bestimmt ZFS die optimale Blockgröße selbst und zutreffend. Dies sollte man aber kontrollieren.
  • Handelt es sich bei dem vdev um einen File (z.B. bei Tests), sollte man die Blockgröße des darunterliegenden Filesystems wählen.


logische Blocks, records Bearbeiten

  • Ein logischer Block wird bei einem Filesystem Dataset als record bezeichnet, seine Größe als recordsize.
  • Die Größe eines logischen Blocks wird bei einem Volume Dataset als volblocksize bezeichnet.
  • Mit logischen Blöcken arbeiten viele der integrierten Funktionen, z.B:
    • Prüfsummenbildung
    • Komprimierung
    • Deduplizierung
  • Die recordsize kann unabhängig von der physischen Blockgröße der vdevs entweder für einen ganzen Pool oder einzelne Datasets gesetzt werden als Vielfaches von 512 Byte.
  • Der Default-Wert beträgt 128 KiB (= 250 * 512B). Zulässiger Wertebereich: 512 B - 1 MiB (dank Videostreaming).
  • Eine recordsize kann jederzeit verändert werden. Die Änderung gilt dann für neu anzulegende Blöcke, nicht rückwirkend.
  • Eine recordsize ist eine Obergrenze und nicht eine feste Größe. Werden Dateien geschrieben, die kleiner sind, so wird ein kleiner Block angelegt. Sind die Daten größer als die Obergrenze, werden sie über mehrere logische Blöcke verteilt. Diese Dynamik hat den entscheidenden Vorteil, dass große Blöcke eingestellt werden können, während kleine Dateien trotzdem keinen ganzen Block belegen. Auf diese Weise wird der von herkömmlichen Dateisystemen bekannte Overhead vermieden.
  • Zur Sicherung der Datenintegrität speichert ZFS Prüfsummen zu jedem logischen Block ab.


Metaslabs Bearbeiten

ZFS betreibt einen hohen Aufwand, Daten so abzulegen, dass sie schnell geschrieben und gelesen werden können. Dazu muss ZFS wissen, welche physikalischen Blöcke auf einer Platte frei und welche bereits belegt sind. Die Zahl dieser Blöcke ist zu groß, als dass man eine direkte Buchführung betreiben könnte. Daher wurden Metaslabs eingeführt.

ZFS teilt also ein vdev in standardmäßig 200 (Diese Anzahl kann man hier nachlesen und einstellen: /sys/module/zfs/parameters/metaslabs_per_vdev) gleich große Metaslabs auf. Ein Metaslab besteht also aus zahlreichen physikalischen Blöcken.

Wenn ZFS schreiben will, sucht es sich einen einen zusammenhängenden Speicherbreich in Form freier Metaslabs, in den alle Daten der anstehenden Transaktion passen. Wenn der Pool voller wird, gibt es diesen zusammenhängenden Bereich nicht mehr und die Daten müssen auf mehrere Metaslabs, die nicht aufeinanderfolgen, verteilt werden. Deswegen nimmt die Performance ab, wenn der Pool voller und/oder stärker fragmentiert ist.

Zuerst werden die schnelleren Metaslabs auf den Außenbahnen der Platten vollgeschrieben.

zdb kann einen Eindruck von der Belegung und Fragmentierung der Metaslabs vermittlen: "sudo zdb -mmm zpooltest"

Anpassung der Anzahl der Metaslabs Bearbeiten

Die Anzahl der pro vdev anzulegenden Metaslabs kann entweder über das sysfs oder dem Kernel-Modul zu übergebende Parameter angepasst werden.

Um die Anzahl der Metaslabs von den standardmäßig 200 auf 300 zu erhöhen, kann folgendes Kommando verwendet werden:

user> echo 300 > /sys/module/zfs/parameters/metaslabs_per_vdev

Soll die Änderung auch über einen Neustart des Systems hinweg bestehen bleiben, muss die Änderung über Parameter des Kernel-Moduls vorgenommen werden.

Benchmarks mit mehr und weniger Metaslabs haben gezeigt, dass in beiden Fällen wesentlich geringere Geschwindigkeiten erreicht werden. Demnach scheint ZFS für den Standardwert von 200 Metaslabs pro vdev optimiert zu sein.


To-Do:

{{{1}}}