Der Leistungsabfall tritt auf, wenn Ihr Zpool entweder sehr voll oder sehr fragmentiert ist. Der Grund dafür ist der Mechanismus der Erkennung freier Blöcke, der mit ZFS verwendet wird. Im Gegensatz zu anderen Dateisystemen wie NTFS oder ext3 gibt es keine Block-Bitmap, die anzeigt, welche Blöcke belegt und welche frei sind. Stattdessen unterteilt ZFS Ihr zvol in (normalerweise 200) größere Bereiche, die als "Metaslabs" bezeichnet werden, und speichert AVL-Bäume 1 mit freien Blockinformationen (Space Map) in jedem Metaslab. Der ausgeglichene AVL-Baum ermöglicht eine effiziente Suche nach einem Block, der der Größe der Anforderung entspricht.
Obwohl dieser Mechanismus aus Gründen der Skalierbarkeit gewählt wurde, stellte er sich leider auch als großer Schmerz heraus, wenn ein hoher Grad an Fragmentierung und / oder Raumnutzung auftritt. Sobald alle Metaslabs eine signifikante Datenmenge enthalten, erhalten Sie eine große Anzahl kleiner Bereiche mit freien Blöcken im Gegensatz zu einer kleinen Anzahl großer Bereiche, wenn der Pool leer ist. Wenn ZFS dann 2 MB Speicherplatz zuweisen muss, beginnt es mit dem Lesen und Auswerten aller Speicherplatzzuordnungen von Metaslabs, um entweder einen geeigneten Block zu finden oder eine Möglichkeit zu finden, die 2 MB in kleinere Blöcke aufzuteilen. Dies dauert natürlich einige Zeit. Was noch schlimmer ist, ist die Tatsache, dass es eine ganze Reihe von E / A-Operationen kosten wird, da ZFS tatsächlich alle Speicherplatzzuordnungen von den physischen Datenträgern lesen würde . Für irgendeinen Ihrer Schreiben.
Der Leistungsabfall kann erheblich sein. Wenn Sie Lust auf schöne Bilder haben, werfen Sie einen Blick auf den Blog-Post bei Delphix, in dem einige Zahlen aus einem (stark vereinfachten, aber dennoch gültigen) ZFS-Pool entnommen wurden. Ich klaue schamlos eines der Diagramme - sehen Sie sich die blauen, roten, gelben und grünen Linien in diesem Diagramm an, die Pools mit einer Kapazität von 10%, 50%, 75% und 93% gegen den Schreibdurchsatz in darstellen KB / s, während sie im Laufe der Zeit fragmentiert werden:
Eine schnelle und schmutzige Lösung dafür war traditionell der Metaslab-Debugging- Modus (nur echo metaslab_debug/W1 | mdb -kw
zur Laufzeit verfügbar, um die Einstellung sofort zu ändern). In diesem Fall werden alle Speicherplatzzuordnungen im RAM des Betriebssystems gespeichert, sodass bei jedem Schreibvorgang keine übermäßigen und teuren E / A-Vorgänge erforderlich sind. Letztendlich bedeutet dies auch, dass Sie mehr Speicher benötigen, insbesondere für große Pools. Dies ist also eine Art RAM für die Speicherung des Pferdehandels. Ihr 10-TB-Pool kostet Sie wahrscheinlich 2-4 GB Speicher 2 , aber Sie können ihn ohne großen Aufwand auf 95% der Auslastung bringen.
1 es ist etwas komplizierter, wenn Sie interessiert sind, schauen Sie sich Bonwicks Beitrag auf Weltraumkarten für Details an
2 Wenn Sie eine Möglichkeit zum Berechnen einer Obergrenze für den Speicher benötigen, ermitteln Sie mithilfe zdb -mm <pool>
von die Anzahl der segments
aktuell verwendeten Speicher in jedem Metaslab und dividieren Sie sie durch zwei, um ein Worst-Case-Szenario zu modellieren. Auf jedes belegte Segment folgt ein freies ), multiplizieren Sie es mit der Datensatzgröße für einen AVL-Knoten (zwei Speicherzeiger und ein Wert, angesichts der 128-Bit-Natur von zfs und der 64-Bit-Adressierung würden sich 32 Byte summieren, obwohl die Leute im Allgemeinen 64 Byte für einige annehmen Grund).
zdb -mm tank | awk '/segments/ {s+=$2}END {s*=32/2; printf("Space map size sum = %d\n",s)}'
Hinweis: Die grundlegende Gliederung ist in diesem Beitrag von Markus Kovero auf der zfs-discussion-Mailingliste enthalten , obwohl er meiner Meinung nach einige Fehler in seiner Berechnung gemacht hat, die ich hoffentlich in meiner korrigiert habe.
volume
auf 8.5T beschränke und nie wieder darüber nachdenke. Ist das korrekt?