{"id":20698,"date":"2026-08-16T11:48:38","date_gmt":"2026-08-16T09:48:38","guid":{"rendered":"https:\/\/webhosting.de\/xfs-allocation-groups-nvme-performance-tuning-storagegrid\/"},"modified":"2026-08-16T11:48:38","modified_gmt":"2026-08-16T09:48:38","slug":"xfs-allokeringsgrupper-ydeevneoptimering-af-nvme-storagegrid","status":"publish","type":"post","link":"https:\/\/webhosting.de\/da\/xfs-allocation-groups-nvme-performance-tuning-storagegrid\/","title":{"rendered":"XFS-allokeringsgrupper: S\u00e5dan udnytter du ydeevnen optimalt p\u00e5 NVMe-systemer"},"content":{"rendered":"<p><strong>XFS NVMe<\/strong> entfaltet seine St\u00e4rke erst, wenn ich Allocation Groups, Blockgr\u00f6\u00dfen, Mount-Optionen und den I\/O\u2011Scheduler konsequent auf die Eigenschaften moderner NVMe\u2011SSDs abstimme. Dieser Beitrag zeigt konkret, wie ich ein XFS\u2011Dateisystem auf NVMe plane, formatiere und betreibe, damit AG\u2011Parallelit\u00e4t, Log\u2011Tuning und Hardware\u2011Queue\u2011Tiefe messbaren Durchsatz und geringe Latenz liefern.<\/p>\n\n<h2>Zentrale Punkte<\/h2>\n\n<ul>\n  <li><strong>AG-Design<\/strong>: Genug Allocation Groups f\u00fcr Parallelit\u00e4t, aber ohne \u00fcberm\u00e4\u00dfigen CPU\u2011Overhead w\u00e4hlen.<\/li>\n  <li><strong>Blockgr\u00f6\u00dfe<\/strong>: Dateisystembl\u00f6cke an physische 4K\u2011Sektoren koppeln, um Mehrfachzugriffe zu vermeiden.<\/li>\n  <li><strong>Mount-Tuning<\/strong>: noatime, allocsize, logbufs\/logbsize gezielt kombinieren statt Default.<\/li>\n  <li><strong>Scheduler<\/strong>: \u201enone\u201c oder \u201emq\u2011deadline\u201c je nach Latenz\u2011Zielen testen und festlegen.<\/li>\n  <li><strong>Workloads<\/strong>: Datenbank, Streaming und KI\u2011Scratch mit passender AG\u2011Anzahl und readahead ausrichten.<\/li>\n<\/ul>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/nvme-performance-8752.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Warum Allocation Groups NVMe beschleunigen<\/h2>\n\n<p>Allocation Groups trennen freie Bl\u00f6cke, Inodes und B+-B\u00e4ume in voneinander unabh\u00e4ngige Bereiche, sodass mehrere Threads gleichzeitig arbeiten k\u00f6nnen und <strong>Sperren<\/strong> seltener greifen. Genau diese Aufteilung passt zu NVMe, das mit vielen Queues und tiefer Parallelit\u00e4t Anfragen zeitgleich bedient und damit Block\u2011Konflikte reduziert. In der Praxis \u00fcbersetze ich Hardware\u2011Parallelit\u00e4t durch ausreichend viele AGs in parallele Allokationen und schnelle Metadaten\u2011Updates, was Latenzspitzen gl\u00e4ttet. Ein <a href=\"https:\/\/webhosting.de\/ext4-xfs-zfs-hosting-performance-vergleich-storage\/\">Performance-Vergleich<\/a> von Dateisystemen zeigt h\u00e4ufig, wie XFS bei parallelen Zugriffen skaliert, w\u00e4hrend sequentielle Lasten weiter zuverl\u00e4ssig laufen. Wichtig bleibt jedoch die Balance: Zu wenige AGs limitieren parallele Allokationen, zu viele kosten sp\u00fcrbar <strong>CPU-Zeit<\/strong>.<\/p>\n\n<h2>AG-Anzahl und AG-Gr\u00f6\u00dfe bestimmen<\/h2>\n\n<p>Bei der Formatierung setze ich die AG\u2011Anzahl bewusst, typischerweise im Spektrum von einigen Dutzend bis hin zu 64\u2013128 AGs pro Terabyte, um ausreichend Nebenl\u00e4ufigkeit ohne \u00fcbertriebenen Verwaltungsaufwand zu erhalten und die <strong>Parallelit\u00e4t<\/strong> auszusch\u00f6pfen. Mit <code>mkfs.xfs -f -d agcount=64 \/dev\/nvme0n1<\/code> lege ich die Verteilung explizit fest; \u00fcber <code>-d size=<\/code> l\u00e4sst sich alternativ die AG\u2011Gr\u00f6\u00dfe steuern. F\u00fcr Workloads mit vielen kleinen Dateien w\u00e4hle ich eher mehr, f\u00fcr gro\u00dfe sequentielle Streams etwas weniger AGs, um CPU\u2011Last im Griff zu behalten. Extremwerte meide ich, weil sehr kleine AGs in gro\u00dfer Zahl beim Auff\u00fcllen des Dateisystems viel Verwaltung verursachen. Entscheidend bleibt: Ich orientiere mich an Kapazit\u00e4t, RAM\u2011Ausstattung und typischer I\/O\u2011Charakteristik, damit Allokationen gleichm\u00e4\u00dfig \u00fcber <strong>AGs<\/strong> streuen.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/xfs_allocation_meeting_1034.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Blockgr\u00f6\u00dfen korrekt an die Hardware koppeln<\/h2>\n\n<p>Viele NVMe\u2011SSDs arbeiten intern mit 4K\u2011Sektoren, auch wenn sie extern 512 Byte anbieten, daher richte ich die Dateisystemblockgr\u00f6\u00dfe auf 4096 Byte aus und senke so interne Read\u2011Modify\u2011Write\u2011Zyklen f\u00fcr <strong>Schreibzugriffe<\/strong>. Bei der Formatierung nutze ich beispielsweise <code>mkfs.xfs -f -b size=4096 \/dev\/nvme0n1<\/code>, wenn die physische Sektorgr\u00f6\u00dfe 4K betr\u00e4gt. Ein falsch ausgerichtetes Dateisystem erzeugt unn\u00f6tige Zusatz\u2011I\/Os, was gerade bei zuf\u00e4lligen kleinen Writes f\u00fchlbar bremst. Die richtige Blockgr\u00f6\u00dfe macht Zugriffe konsistent, gl\u00e4ttet die Latenz und liefert bessere IOPS bei kurzen Anfragen. F\u00fcr Spezialf\u00e4lle mit sehr gro\u00dfen Sequential\u2011Jobs kombiniere ich 4K\u2011Bl\u00f6cke mit gr\u00f6\u00dferem readahead, damit die <strong>Durchsatzrate<\/strong> steigt.<\/p>\n\n<h2>Mount-Optionen f\u00fcr NVMe-Last<\/h2>\n\n<p>Ohne Tuning l\u00e4uft XFS bereits flott, doch gezielte Mount\u2011Optionen holen noch Reserven heraus und sparen unn\u00f6tige Metadaten\u2011Aktualisierungen bei <strong>Leselast<\/strong>. Ich aktiviere <code>noatime,nodiratime<\/code>, setze je nach Workload eine gr\u00f6\u00dfere <code>allocsize<\/code> (z. B. 64M) und erh\u00f6he Logpuffer mit <code>logbufs=8,logbsize=256k<\/code> f\u00fcr mehr Metadaten\u2011Durchsatz. Statt <code>discard<\/code> am Mount f\u00fchre ich <code>fstrim<\/code> periodisch aus, damit TRIM\u2011Befehle geb\u00fcndelt laufen. Eine Beispielzeile in <code>\/etc\/fstab<\/code> sieht so aus: <code>\/dev\/nvme0n1 \/data xfs noatime,nodiratime,allocsize=64m,logbufs=8,logbsize=256k 0 0<\/code>. Die folgende Tabelle ordnet g\u00e4ngige Optionen ihrem Effekt und typischen Einsatzfall zu, damit ich Entscheidungen schneller treffe und die <strong>Konfiguration<\/strong> dokumentiere.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Option<\/th>\n      <th>Wirkung<\/th>\n      <th>Wann einsetzen<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code>noatime,nodiratime<\/code><\/td>\n      <td>Reduziert Metadaten\u2011Writes bei Zugriffen<\/td>\n      <td>Viele Reads, Web\u2011\/Analyse\u2011Workloads<\/td>\n    <\/tr>\n    <tr>\n      <td><code>allocsize=64m<\/code><\/td>\n      <td>B\u00fcndelt Allokationen, mindert Fragmentierung<\/td>\n      <td>Gro\u00dfe sequentielle Schreibstr\u00f6me<\/td>\n    <\/tr>\n    <tr>\n      <td><code>logbufs=8<\/code><\/td>\n      <td>Mehr parallele Logpuffer f\u00fcr Metadaten<\/td>\n      <td>Transaktionslast, viele kleine Updates<\/td>\n    <\/tr>\n    <tr>\n      <td><code>logbsize=256k<\/code><\/td>\n      <td>Gr\u00f6\u00dfere Log\u2011Schreibbl\u00f6cke<\/td>\n      <td>H\u00f6herer Metadaten\u2011Durchsatz<\/td>\n    <\/tr>\n    <tr>\n      <td>kein <code>discard<\/code><\/td>\n      <td>Vermeidet synchrone TRIM\u2011Kosten<\/td>\n      <td>Stattdessen regelm\u00e4\u00dfiges <code>fstrim<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/xfs-nvme-performance-optimization-3023.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>I\/O-Scheduler: none, mq-deadline und Co.<\/h2>\n\n<p>NVMe\u2011Controller ordnen Anfragen selbst effizient, daher fahre ich oft mit <code>none<\/code> am besten und halte so den <strong>Overhead<\/strong> niedrig. F\u00fcr Workloads mit strenger Latenzanforderung teste ich <code>mq-deadline<\/code>, weil es Antwortzeiten stabilisieren kann, auch wenn der Maximaldurchsatz geringf\u00fcgig sinkt. W\u00e4hrend <code>bfq<\/code> f\u00fcr Interaktivit\u00e4t punkten kann, ist er auf Server\u2011NVMe selten erste Wahl. Die Wahl treffe ich erst nach Messungen mit <code>fio<\/code>, die IOPS, Durchsatz und Latenz getrennt f\u00fcr Read\/Write und Random\/Sequential erfassen. Details zum Abw\u00e4gen der Optionen vertiefe ich in diesem kompakten <a href=\"https:\/\/webhosting.de\/io-scheduler-linux-noop-mq-deadline-bfq-serverboost\/\">I\/O-Scheduler Guide<\/a>, bevor ich die Einstellung produktiv setze.<\/p>\n\n<h2>Workloads gezielt abstimmen<\/h2>\n\n<p>Datenbanken mit vielen Commits profitieren von moderater AG\u2011Anzahl, ausgerichteten 4K\u2011Bl\u00f6cken, <code>noatime<\/code> und angehobenem <strong>logbsize<\/strong>, damit Metadaten\u2011Transaktionen z\u00fcgig laufen. Analytics\u2011Jobs und Streaming\u2011Pipelines setze ich mit gr\u00f6\u00dferer <code>allocsize<\/code> und mehr readahead auf hohen sequenziellen Durchsatz. F\u00fcr KI\/ML\u2011Scratch\u2011Daten und viele parallele Worker w\u00e4hle ich eher mehr AGs, <code>noatime<\/code>, geb\u00fcndelte Allokationen und <code>none<\/code> als Scheduler. Backups oder Archivl\u00e4ufe profitieren zus\u00e4tzlich von periodischem <code>fstrim<\/code>, um SSD\u2011Garbage\u2011Collection zu entlasten. Jede Anpassung sichere ich mit reproduzierbaren Messreihen ab, bevor ich die <strong>Defaults<\/strong> dauerhaft ersetze.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/xfs_allocation_nvme_4213.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>H\u00e4ufige Symptome schnell deuten<\/h2>\n\n<p>Meldet XFS \u201eNo space left on device\u201c trotz offensichtlich freier Kapazit\u00e4t, ist oft eine einzelne AG ausgesch\u00f6pft, weshalb ich Datenverteilung, <strong>agcount<\/strong> und freie Metadatenr\u00e4ume pr\u00fcfe. Unerwartet hohe Latenz bei kleinen Random\u2011Writes deute ich meist als Zeichen f\u00fcr ungeeignete Blockausrichtung, zu kleine <code>allocsize<\/code> oder \u00fcberaktive Metadaten\u2011Updates. In solchen F\u00e4llen helfen 4K\u2011Bl\u00f6cke, gr\u00f6\u00dfere Allokationshappen und <code>noatime<\/code>, um Schreibvorg\u00e4nge zu b\u00fcndeln. Steigt die CPU\u2011Last im Dateisystem auff\u00e4llig, war die AG\u2011Anzahl wom\u00f6glich zu hoch gew\u00e4hlt, speziell wenn das Filesystem nahezu gef\u00fcllt ist. Dann reduziere ich AGs bei einer Neuformatierung oder erweitere die Partition, um <strong>Verwaltung<\/strong> zu senken.<\/p>\n\n<h2>Parameter-\u00dcbersicht als Schnell-Check<\/h2>\n\n<p>F\u00fcr wiederkehrende Setups halte ich eine kurze Checkliste parat, die ich vor jeder Formatierung abarbeite und so <strong>Konstanz<\/strong> in die Ergebnisse bringe. Erstens pr\u00fcfe ich physische Sektorgr\u00f6\u00dfe, Queue\u2011Tiefe und Controller\u2011Features der NVMe\u2011Ger\u00e4te. Danach lege ich AG\u2011Anzahl oder AG\u2011Gr\u00f6\u00dfe fest und richte die Blockgr\u00f6\u00dfe an 4K aus. Anschlie\u00dfend definiere ich Mount\u2011Optionen, die zur Last passen, und plane ein periodisches <code>fstrim<\/code>. Zuletzt teste ich I\/O\u2011Scheduler\u2011Varianten und dokumentiere die schnellste Kombination f\u00fcr den jeweiligen Anwendungsfall.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/xfs_allocation_nvme_3791.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Schrittweise Planung eines neuen XFS auf NVMe<\/h2>\n\n<p>Zu Beginn ermittle ich Kapazit\u00e4t, physische Sektorgr\u00f6\u00dfe, typische Dateigr\u00f6\u00dfen und parallele Thread\u2011Zahl, damit die <strong>AG-Planung<\/strong> fundiert startet. Danach formatiere ich mit angepasster AG\u2011Anzahl, 4K\u2011Blockgr\u00f6\u00dfe und optionalen Inode\u2011Parametern, falls viele kleine Dateien zu erwarten sind. Im n\u00e4chsten Schritt mounte ich mit <code>noatime<\/code>, passender <code>allocsize<\/code> sowie optimierten Log\u2011Parametern und pr\u00fcfe die Resultate mit <code>fio<\/code>. Darauf folgt die Scheduler\u2011Wahl, wobei ich <code>none<\/code> und <code>mq-deadline<\/code> vergleiche und dabei sowohl IOPS als auch Latenz im Blick behalte. Abschlie\u00dfend etabliere ich Monitoring und geplantes <code>fstrim<\/code>, damit die Performance langfristig <strong>konstant<\/strong> bleibt und keine \u00dcberraschungen auftreten.<\/p>\n\n<h2>Einordnung in Hosting-Umgebungen<\/h2>\n\n<p>In Hosting\u2011Szenarien mit Containern, Web\u2011Stacks und Datenbanken zahlt sich eine sauber geplante XFS\u2011Konfiguration direkt in Antwortzeit und <strong>Durchsatz<\/strong> aus. Ich ber\u00fccksichtige dabei die Queue\u2011Tiefe und die Zahl paralleler Worker, um AG\u2011Anzahl und Scheduler sinnvoll zu kombinieren. Eine fundierte Erkl\u00e4rung, warum die Warteschlangenl\u00e4nge auf NVMe den Takt vorgibt, habe ich mir im Beitrag zur <a href=\"https:\/\/webhosting.de\/server-storage-queue-depth-nvme-performance-speed\/\">Queue Depth<\/a> erarbeitet. F\u00fcr datenintensive Microservices erh\u00f6he ich oft <code>readahead<\/code>, b\u00fcndele Allokationen und messe iterativ nach jeder \u00c4nderung. Wer seine Anwendungen auf leistungsf\u00e4higen Managed\u2011 oder Root\u2011Servern betreibt, profitiert damit von niedriger Latenz, hoher Parallelit\u00e4t und gut planbarem Betrieb auf <strong>XFS<\/strong>.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/nvme-xfs-performance-3294.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Reflink, Inodes und Metadaten-Features bewusst w\u00e4hlen<\/h2>\n\n<p>Bei der Formatierung entscheide ich, ob CoW\/Reflink f\u00fcr meinen Anwendungsfall sinnvoll ist. Mit <code>mkfs.xfs -m reflink=1<\/code> aktiviere ich Copy\u2011on\u2011Write und schnelle Klone, was beim Erstellen vieler Kopien, VM\u2011Images oder Build\u2011Artefakte Platz und Zeit spart. F\u00fcr stark schreibintensive Datenbanken deaktiviere ich Reflink (<code>reflink=0<\/code>), um Metadaten\u2011Overhead zu reduzieren und Log\u2011Druck zu senken. Zus\u00e4tzlich pr\u00fcfe ich <strong>finobt<\/strong> (Free\u2011Inode\u2011B\u2011Tree), der Allokationsentscheidungen bei vielen Inodes beschleunigt und in aktuellen Tools typischerweise ohnehin aktiv ist.<\/p>\n\n<p>Die <strong>Inode\u2011Gr\u00f6\u00dfe<\/strong> bestimme ich \u00fcber <code>-i size=<\/code>. F\u00fcr Workloads mit vielen Extended Attributes (ACLs, SELinux, Applikations\u2011Metadata) w\u00e4hle ich 512 oder 1024 Byte, damit Attribute h\u00e4ufiger im Inode Platz finden und nicht in separaten Bl\u00f6cken landen. Beispiel: <code>mkfs.xfs -f -b size=4096 -i size=512 \/dev\/nvme0n1<\/code>. Gr\u00f6\u00dfere Inodes kosten etwas Platz, sparen aber Zugriffe, wenn Metadaten h\u00e4ufig gelesen oder geschrieben werden. Features wie <strong>bigtime<\/strong> verl\u00e4ngern den nutzbaren Zeitstempelbereich moderner Systeme und sind bei neuen Installationen sinnvoll, ohne messbaren Performance\u2011Nachteil. Auf optionale Strukturen wie <strong>rmapbt<\/strong> verzichte ich f\u00fcr reine Performance\u2011Volumes meist, da sie prim\u00e4r Verwaltbarkeit und Pr\u00fcfbarkeit erh\u00f6hen, aber Mehraufwand verursachen.<\/p>\n\n<h2>Externes Log, Loggr\u00f6\u00dfe und Stripe\u2011Ausrichtung<\/h2>\n\n<p>F\u00fcr Metadaten\u2011schwere Lasten lohnt ein separates Log\u2011Ger\u00e4t (Journal) auf einer zweiten, sehr latenzarmen NVMe, um Konkurrenz zwischen Nutzdaten und Log\u2011Writes zu minimieren. Das setze ich bei der Formatierung mit <code>-l logdev=\/dev\/nvme1n1,size=<\/code> um und halte die Loggr\u00f6\u00dfe so, dass Burst\u2011Phasen nicht dauernd Log\u2011Forces ausl\u00f6sen (h\u00e4ufig 1\u20134 GiB, je nach Transaktionsmuster). Zusammen mit <code>logbufs<\/code>\/<code>logbsize<\/code> am Mount stabilisiert ein externes Log Transaktionszeiten merklich, wenn viele kleine Dateien oder Metadaten\u2011Updates anfallen.<\/p>\n\n<p>Liegt die NVMe hinter einem RAID oder Device\u2011Mapper, richte ich XFS auf Stripe\u2011Gr\u00f6\u00dfen aus, damit Schreibvorg\u00e4nge Stripe\u2011Grenzen sauber treffen. Das erfolgt bei der Formatierung \u00fcber <code>-d su=&lt;stripe_unit&gt;,sw=&lt;stripe_width_in_units&gt;<\/code>. Anschlie\u00dfend pr\u00fcfe ich die Werte mit <code>xfs_info \/mount<\/code>. Wichtig: Diese Parameter lassen sich sp\u00e4ter nicht ohne Neuformatierung \u00e4ndern. Auf Einzel\u2011NVMe ohne darunterliegendes Striping \u00fcberlasse ich XFS das Autotuning.<\/p>\n\n<h2>Partition- und Block\u2011Ausrichtung sicherstellen<\/h2>\n\n<p>Bevor ich formatiere, lege ich Partitionen 1 MiB\u2011ausgerichtet an, damit Dateisystembl\u00f6cke sauber auf physische 4K\u2011Grenzen fallen. Mit <code>parted -a optimal<\/code> oder entsprechender GPT\u2011Konfiguration verhindere ich ungl\u00fcckliche Offsets. Die effektive physische und logische Sektorgr\u00f6\u00dfe verifiziere ich mit <code>cat \/sys\/block\/nvme0n1\/queue\/physical_block_size<\/code> und <code>logical_block_size<\/code>. Erst wenn diese Basis stimmt, entfalten 4K\u2011Bl\u00f6cke und Allokationshappen ihre volle Wirkung.<\/p>\n\n<h2>Direct I\/O, Page Cache und Writeback steuern<\/h2>\n\n<p>F\u00fcr Datenbanken und Log\u2011Str\u00f6me, die ihren eigenen Cache managen, setze ich gezielt <strong>O_DIRECT<\/strong>, um doppeltes Caching im Page Cache zu vermeiden. XFS skaliert hier sehr gut, solange ich nicht gleichzeitig dieselben Dateien gemischt gepuffert und direkt beschreibe. F\u00fcr Streaming\u2011Workloads beschleunigt eine h\u00f6here <code>readahead<\/code> den Durchsatz: <code>blockdev --setra 4096 \/dev\/nvme0n1<\/code> (entspricht 2 MiB) ist ein pragmatischer Startwert, den ich messe und bei Bedarf feiner einstelle.<\/p>\n\n<p>Zur Systembalance passe ich die Writeback\u2011Schwellen vorsichtig an. Statt Prozentwerten setze ich auf Gr\u00f6\u00dfenangaben, um bei gro\u00dfen RAM\u2011Konfigurationen nicht zu viel Dirty\u2011Data anzusammeln. Beispiel (mit Bedacht testen):<\/p>\n\n<pre><code>sysctl -w vm.dirty_background_bytes=268435456\nsysctl -w vm.dirty_bytes=2147483648\n<\/code><\/pre>\n\n<p>So verhindere ich lange Flush\u2011Wellen, die Latenzen anheben. Diese Settings dokumentiere ich je Host, damit sie reproduzierbar bleiben und nicht unbemerkt von Distribution\u2011Defaults \u00fcbersteuert werden.<\/p>\n\n<h2>Queue- und CPU\u2011Topologie ausnutzen<\/h2>\n\n<p>NVMe nutzt Multi\u2011Queue I\/O: Pro CPU\u2011Core existieren i. d. R. eigene Hardware\u2011Queues, sodass ich IRQ\u2011Verteilung und CPU\u2011Affinity nicht dem Zufall \u00fcberlasse. Ein laufender <code>irqbalance<\/code> ist die Baseline; bei Latenz\u2011Spezialf\u00e4llen pinne ich die NVMe\u2011IRQs per <code>\/proc\/irq\/*\/smp_affinity<\/code> gezielt an NUMA\u2011nahe Cores. <code>cat \/sys\/block\/nvme0n1\/queue\/scheduler<\/code> zeigt mir den aktiven Scheduler, <code>nr_requests<\/code> und <code>rq_affinity<\/code> beeinflussen, wie Anfragen auf Queues verteilt werden. F\u00fcr sehr parallelisierte Worker erh\u00f6he ich testweise <code>\/sys\/block\/nvme0n1\/queue\/nr_requests<\/code> moderat, um Spitzen besser abzufedern, ohne den Treiber zu \u00fcberf\u00fcllen.<\/p>\n\n<p>Zus\u00e4tzlich kann ich Interrupt\u2011Kollabierung der NVMe\u2011Ger\u00e4te feinsteuern (Controller\u2011Feature). Eine ma\u00dfvolle Erh\u00f6hung der Coalescing\u2011Parameter gl\u00e4ttet IRQ\u2011Last, darf aber die Latenzziele nicht rei\u00dfen. Solche Eingriffe belege ich immer mit <code>fio<\/code>\u2011Latenzpercentiles, bevor sie in Produktion landen.<\/p>\n\n<h2>Quotas, Projekte und Isolation<\/h2>\n\n<p>In Multi\u2011Tenant\u2011Umgebungen setze ich auf <strong>Project Quotas<\/strong>, damit Lasten und Platzverbrauch sauber voneinander getrennt bleiben. Ich mounte mit <code>prjquota<\/code> und verwalte Grenzen \u00fcber <code>xfs_quota<\/code> samt <code>\/etc\/projects<\/code> und <code>\/etc\/projid<\/code>. So lassen sich etwa Build\u2011Verzeichnisse, Datenbank\u2011Instanzen oder Mandantenverzeichnisse hart begrenzen, ohne die AG\u2011Parallelit\u00e4t zu beschneiden.<\/p>\n\n<p>F\u00fcr ingest\u2011lastige Verzeichnisb\u00e4ume, die viele gro\u00dfe Dateien sequenziell schreiben, kann der <strong>filestreams<\/strong>\u2011Allocator sinnvoll sein. Er h\u00e4lt Dateien eines Verzeichnisses enger zusammen und reduziert Fragmentierung. Ich aktiviere ihn gezielt per Mount\u2011Option f\u00fcr Volumes, die klar streaming\u2011orientiert sind, und messe den Effekt auf Durchsatz und CPU\u2011Last.<\/p>\n\n<h2>Wachstum, Snapshots und Lebenszyklus<\/h2>\n\n<p>XFS kann <strong>online wachsen<\/strong>, nicht aber schrumpfen. Deshalb plane ich Kapazit\u00e4t und AG\u2011Layout so, dass k\u00fcnftige Erweiterungen via LVM\/VMDK problemlos m\u00f6glich sind. Mit <code>xfs_growfs \/mount<\/code> erweitere ich das Dateisystem nach oben, die AG\u2011Struktur w\u00e4chst dabei mit. Parameter wie <code>sunit<\/code> und <code>swidth<\/code> sind festgelegt \u2013 wer RAID\u2011Geometrien \u00e4ndert, sollte daher Neuformatierung und Restore einplanen.<\/p>\n\n<p>F\u00fcr konsistente <strong>Snapshots<\/strong> in Kombination mit LVM oder Storage\u2011Backends friere ich das Dateisystem kurz ein: <code>xfs_freeze -f \/mount<\/code>, Snapshot erstellen, <code>xfs_freeze -u \/mount<\/code>. Das minimiert Log\u2011Replays und garantiert saubere Wiederherstellungen. Zur Laufzeitgesundheit plane ich regelm\u00e4\u00dfiges <code>xfs_scrub<\/code> (wo verf\u00fcgbar) und halte <code>xfs_repair<\/code> als Offline\u2011Tool parat. SMART\u2011Daten, <code>nvme smart-log<\/code> und <code>iostat -x<\/code> stehen auf meiner Watchlist, um Degradation fr\u00fch zu erkennen.<\/p>\n\n<h2>Testmethodik und belastbare Baselines<\/h2>\n\n<p>Bevor ich Defaults ersetze, messe ich reproduzierbar. Ich starte mit klaren <code>fio<\/code>\u2011Profiles, die IOPS, Durchsatz und Latenz getrennt betrachten und Warm\u2011up\u2011Phasen beinhalten:<\/p>\n\n<pre><code>[global]\nioengine=io_uring\ndirect=1\nruntime=60\ntime_based=1\ngroup_reporting=1\nrandrepeat=0\n\n[randread-4k]\nfilename=\/data\/testfile\nrw=randread\nbs=4k\niodepth=64\nnumjobs=8\n\n[randwrite-4k]\nfilename=\/data\/testfile\nrw=randwrite\nbs=4k\niodepth=64\nnumjobs=8\n\n[seqread-1m]\nfilename=\/data\/testfile\nrw=read\nbs=1m\niodepth=32\nnumjobs=4\n\n[seqwrite-1m]\nfilename=\/data\/testfile\nrw=write\nbs=1m\niodepth=32\nnumjobs=4\n<\/code><\/pre>\n\n<p>Je nach Ziel passe ich <code>numjobs<\/code> an die CPU\u2011Kerne und <code>iodepth<\/code> an die gew\u00fcnschte Queue\u2011Tiefe an. Wichtig sind konsistente Randbedingungen (gleicher F\u00fcllstand, identische Mount\u2011Optionen, sauber getrimmtes Volume). Ausrei\u00dfer filtere ich, indem ich mehrere L\u00e4ufe mittlere und 99\u2011Perzentile vergleiche. So treffe ich fundierte Entscheidungen zwischen <code>none<\/code> und <code>mq-deadline<\/code>, zwischen kleinerer und gr\u00f6\u00dferer <code>allocsize<\/code> oder bei der Frage, ob ein externes Log wirklich hilft.<\/p>\n\n<h2>Feinabstimmung von allocsize, Reflink und Co.<\/h2>\n\n<p><code>allocsize<\/code> ist ein n\u00fctzliches Werkzeug, aber kein Allheilmittel. Bei rein zuf\u00e4lligen Klein\u2011Writes erzeugen zu gro\u00dfe Allokationshappen unn\u00f6tigen Schreibaufwand. Ich w\u00e4hle daher je Workload konservative Werte und pr\u00fcfe Fragmentierung sowie Latenz. Mit aktiviertem Reflink meide ich Dauer\u2011Kleinupdates in denselben Dateibereichen, weil CoW zus\u00e4tzliche Metadatenarbeit bedeutet. Brauche ich schnelle Klone, halte ich Log\u2011Puffer gro\u00df und sorge f\u00fcr viel freien, zusammenh\u00e4ngenden Raum in mehreren AGs.<\/p>\n\n<h2>Sichere Defaults: Barriers, Discard und Konsistenz<\/h2>\n\n<p>Schreibbarrieren (<em>Write Barriers<\/em>) und FUA sind auf modernen Stacks standardm\u00e4\u00dfig aktiv \u2013 daran r\u00fcttle ich nicht, um Datenverlustrisiken zu vermeiden. <code>nobarrier<\/code> kommt f\u00fcr mich nicht infrage, selbst wenn einzelne Benchmarks kurzfristig zulegen. <code>discard<\/code> am Mount bleibt aus, der systemweite <code>fstrim<\/code>\u2011Timer erledigt TRIM effizient in Ruhephasen. Diese Kombination liefert mir verl\u00e4sslich niedrige Latenz bei hoher Nachhaltigkeit der SSD\u2011Leistung.<\/p>\n\n<h2>Kurz zusammengefasst<\/h2>\n\n<p>XFS skaliert durch Allocation Groups horizontal und nutzt so den inh\u00e4renten Parallelismus von <strong>NVMe<\/strong> effektiv aus. Ich bestimme AG\u2011Anzahl, Blockgr\u00f6\u00dfen, Mount\u2011Optionen und Scheduler nicht nach Bauchgef\u00fchl, sondern nach Workload\u2011Profil und Messdaten. F\u00fcr kleine Random\u2011Writes z\u00e4hlt saubere Ausrichtung und schlanker Scheduler, f\u00fcr gro\u00dfe Streams eher gro\u00dfz\u00fcgige <code>allocsize<\/code> und readahead. Typische Stolpersteine wie unausgewogene AGs oder synchrone Discards l\u00f6se ich durch Neuaufteilung und periodisches <code>fstrim<\/code>. Wer diese Stellschrauben systematisch anfasst, h\u00e4lt Latenz niedrig, treibt IOPS hoch und sichert dauerhaft <strong>Performance<\/strong>.<\/p>","protected":false},"excerpt":{"rendered":"<p>L\u00e6r, hvordan du konfigurerer XFS-allokeringsgrupper p\u00e5 et NVMe-filsystem med m\u00e5lrettet lagringsoptimering for at opn\u00e5 maksimal ydeevne og skalerbarhed p\u00e5 NVMe-SSD'er.<\/p>","protected":false},"author":1,"featured_media":20691,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[676],"tags":[],"class_list":["post-20698","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server_vm"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"111","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":[],"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"XFS NVMe","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"20691","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/20698","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/comments?post=20698"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/20698\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media\/20691"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media?parent=20698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/categories?post=20698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/tags?post=20698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}