Dies ist eine Fortsetzung von:Schnelle Netzwerkschreibvorgänge mit Speicher großer Kapazität. Das Setup hat sich deutlich verändert.
Ich habe einen Pool mit einem einzelnen raid-z2
Laufwerk mit 6 Laufwerken, alles Exos X18 CMR-Laufwerke. Durch fio
manuelle Tests weiß ich, dass das Array durchschnittlich etwa 800 MB/s sequentielle Schreibvorgänge aushält. Das ist in Ordnung und entspricht der erwarteten Leistung dieses Arrays. Die Maschine ist ein Ryzen5 Pro 2400 GE (4C/8T, 3,8 GHz Boost) mit 32G ECC RAM, NVMe-Boot-/Systemlaufwerk und 2x10Gbps Ethernet-Ports (Intel x550-T2). Ich verwende ein aktuelles Arch-System mit zfs 2.1.2-1.
Mein Anwendungsfall ist ein Videoarchiv mit meist großen (~30 G) komprimierten Videos, die einmal geschrieben und einmal gelesen werden. Ich habe deaktiviert atime
, gesetzt recordsize=1M
, gesetzt compressios=off
und gesetzt, dedup=off
da die Daten eigentlich nicht komprimierbar sind und Tests trotz der Angaben im Internet eine schlechtere Leistung mit compression=lz4
als off
gezeigt haben und es absichtlich keine doppelten Daten gibt. Dieser Pool wird über das Netzwerk via Samba geteilt. Ich habe mein Netzwerk und Samba so weit optimiert, dass die Übertragung von NVMe NTFS auf einem Windows-Rechner zu NVMe ext4 1 GB/s erreicht, also ziemlich nahe daran ist, die 10-Gbit/s-Verbindung mit 9K Jumbo Frames zu sättigen.
Hier stoße ich auf Probleme. Ich möchte ein ganzes 30-G-Videoarchiv mit 1 GB/s auf das raid-z2
Array übertragen können, das nur 800 MB/s sequentielles Schreiben unterstützt. Mein Plan ist, die RAM-basierten Dirty Pages zu verwenden, um den Überlauf zu absorbieren und ihn auf die Festplatte zu spülen, nachdem die Übertragung auf der Clientseite „abgeschlossen“ ist. Ich dachte, dass ich nur Dirty Pages (1024-800)*30~=7G
im RAM brauche, die innerhalb von ca. 10 Sekunden nach Abschluss der Übertragung auf die Festplatte geschwemmt werden können. Ich verstehe die Auswirkungen auf die Datenintegrität und das Risiko ist akzeptabel, da ich die Datei später bis zu einem Monat lang immer noch einmal übertragen kann, falls ein Stromausfall dazu führt, dass die Datei verloren geht oder unvollständig ist.
Ich kann ZFS jedoch nicht dazu bringen, sich wie erwartet zu verhalten ... Ich habe meine /etc/modprobe.d/zfs.conf
Datei folgendermaßen bearbeitet:
options zfs zfs_dirty_data_max_max=25769803776
options zfs zfs_dirty_data_max_max_percent=50
options zfs zfs_dirty_data_max=25769803776
options zfs zfs_dirty_data_max_percent=50
options zfs zfs_delay_min_dirty_percent=80
Ich habe den entsprechenden Befehl ausgeführt, mkinitcpio -P
um mein Initramfs zu aktualisieren, und bestätigt, dass die Einstellungen nach einem Neustart angewendet wurden:
# arc_summary | grep dirty_data
zfs_dirty_data_max 25769803776
zfs_dirty_data_max_max 25769803776
zfs_dirty_data_max_max_percent 50
zfs_dirty_data_max_percent 50
zfs_dirty_data_sync_percent 20
D. h. ich stelle die maximale Anzahl schmutziger Seiten auf 24 G ein, was viel mehr ist als die 7 G, die ich benötige, und warte, bis 80 % davon verbraucht sind, um Schreibvorgänge zu verzögern. Soweit ich weiß, sollte der Pool 19 G in den RAM aufnehmen können, bevor er Schreibvorgänge vom Client (Samba) mit Verzögerung zurückdrängt.
Was ich jedoch beim Schreiben vom Windows-Client aus beobachte, ist, dass die Schreibleistung nach etwa 16 Sekunden bei einer Schreibgeschwindigkeit von ~1 GB/s schlagartig abfällt (es iostat
ist immer noch zu sehen, dass die Festplatten hart daran arbeiten, die Daten zu löschen), was ich nur als Pushback-Mechanismus für die Schreibdrosselung von ZFS bezeichnen kann. Das ergibt jedoch keinen Sinn, denn selbst wenn während der 16 Sekunden nichts gelöscht wurde, hätte es 3 Sekunden später einsetzen müssen. Außerdem fällt es am Ende noch einmal ab, siehe Bild: [ ][https://i.stack.imgur.com/Yd9WH.png]
Ich habe versucht, den zfs_dirty_data_sync_percent
Schreibvorgang früher einzustellen, da der Dirty-Page-Puffer so viel größer als der Standard ist. Außerdem habe ich versucht, die aktive E/A-Skalierung so einzustellen, dass sie zfs_vdev_async_write_active_{min,max}_dirty_percent
früher einsetzt, damit die Schreibvorgänge mit dem großen Dirty-Puffer schneller auf Touren kommen. Beides hat die Position der Klippe nur leicht verschoben, aber nicht annähernd so, wie ich es erwartet hatte.
Fragen:
- Habe ich die Funktionsweise der Schreibdrosselungsverzögerung missverstanden?
- Ist das, was ich versuche, möglich?
- Wenn ja, was mache ich falsch?
Ja, ich weiß, ich jage buchstäblich ein paar Sekunden hinterher und werde den Aufwand, der dafür aufgewendet wurde, nie wieder hereinholen. Das ist ok, es ist an diesem Punkt eine persönliche Angelegenheit zwischen mir und ZFS und eine Grundsatzfrage ;)
Antwort1
Sie müssen zfs_txg_timeout
den Parameter auch vom aktuellen Standardwert von 5 Sekunden auf etwa 7 G/0,2 G/s = 35 s erhöhen, sodass eine Einstellung auf 40 s ausreichen sollte.
In deinem /etc/modprobe.d/zfs.conf
:
options zfs zfs_txg_timeout=40
Beachten Sie, dass der ARC genau das ist: ein „Lese“-Cache ohne Zugriff auf den Schreibcache. Stellen Sie daher sicher, dass Ihr ARC nicht so eingerichtet ist, dass er die zusätzlichen 7 G+ an Daten verbraucht, die Ihr Blockschreibcache pro 30 GB Schreibstrom aufnehmen muss. Der Schreibcache für ZFS ist wie jeder andere einfache Blockschreibcache (wie der commit
Parameter für ext4-Dateisysteme). Führen Sie daher unbedingt Tests außerhalb der Produktion durch, um sicherzustellen, dass während aller Übertragungsszenarien kein RAM-Mangel auftritt.
Antwort2
Jeder Schreibvorgang aktualisiert den ARC, wenn zfs primarycache = all (Standard). Wenn die Leselatenz für die Daten, die Sie gerade schreiben, unwichtig ist, schlage ich vor, zfs primarycache=meta einzustellen.
Antwort3
Sie verfügen derzeit nicht über genügend RAM oder Speicherressourcen für das, was Sie suchen.
Planen Sie auf der Grundlage Ihres gewünschten E/A-Durchsatzes und der Leistung im schlimmsten Fall.
Wenn Sie für den beschriebenen Arbeitsdatensatz unter allen Bedingungen einen Durchsatz von 1 GB/s benötigen, stellen Sie sicher, dass die Anzahl der Festplattenspindeln oder der Schnittstellendurchsatz dies unterstützt.