Was sind die Auswirkungen auf die Leistung von Millionen von Dateien in einem modernen Dateisystem?

30

Nehmen wir an, wir verwenden ext4 (mit aktiviertem dir_index) zum Hosten von etwa 3 Millionen Dateien (mit einer durchschnittlichen Größe von 750 KB) und müssen uns entscheiden, welches Ordnerschema wir verwenden.

In der ersten Lösung wenden wir eine Hash-Funktion auf die Datei an und verwenden einen Ordner mit zwei Ebenen (1 Zeichen für die erste Ebene und 2 Zeichen für die zweite Ebene). Da der filex.forHash also abcde1234 entspricht, speichern wir ihn in / path / a / bc /abcde1234-filex.for.

In der zweiten Lösung wenden wir eine Hash-Funktion auf die Datei an und verwenden einen Ordner mit zwei Ebenen (bestehend aus 2 Zeichen für die erste Ebene und 2 Zeichen für die zweite Ebene). Wenn der filex.forHash also gleich abcde1234 ist , speichern wir ihn in / path / ab / de /abcde1234-filex.for.

Für die erste Lösung haben wir das folgende Schema /path/[16 folders]/[256 folders]mit durchschnittlich 732 Dateien pro Ordner (der letzte Ordner, in dem sich die Datei befinden wird).

Während auf der zweiten Lösung werden wir haben /path/[256 folders]/[256 folders]mit einem Durchschnitt von 45 Dateien pro Ordner .

In Anbetracht dessen, dass wir von diesem Schema aus viele Dateien schreiben / trennen / lesen ( aber meistens lesen ) (im Grunde genommen das Nginx-Caching-System), ist es in Bezug auf die Leistung von Bedeutung, ob wir die eine oder andere Lösung gewählt haben?

Mit welchen Tools können wir dieses Setup überprüfen / testen?

leandro moreira
quelle
7
Natürlich hilft Benchmarking. Dafür ist ext4 möglicherweise das falsche Dateisystem. Ich würde mir XFS ansehen.
ewwhite
4
Ich würde mir nicht nur XFS ansehen , sondern es sofort und ohne weitere Umstände verwenden. Der B + -Baum schlägt jedes Mal die Hash-Tabelle.
Michael Hampton
Vielen Dank für die Tipps, Benchmarking ist zwar etwas schwierig, ich habe es versucht, hdparm -Tt /dev/hdXaber es ist möglicherweise nicht das am besten geeignete Tool.
Leandro Moreira
2
Nein hdparmist nicht das richtige Tool, es ist eine Überprüfung der unformatierten Leistung des Blockgeräts und kein Test des Dateisystems.
HBruijn

Antworten:

28

Der Grund für die Erstellung einer solchen Verzeichnisstruktur ist, dass Dateisysteme eine Datei in einem Verzeichnis suchen müssen. Je größer das Verzeichnis ist, desto langsamer ist diese Operation.

Wie viel langsamer, hängt vom Dateisystemdesign ab.

Das ext4-Dateisystem verwendet einen B-Baum zum Speichern von Verzeichniseinträgen. Es wird erwartet, dass eine Suche in dieser Tabelle eine Zeit von 0 (log n) benötigt. Dies ist in den meisten Fällen weniger als in der naiven linearen Tabelle, die ext3 und frühere Dateisysteme verwendet haben (und wenn dies nicht der Fall ist, ist das Verzeichnis zu klein, um dies zu tun) wirklich wichtig).

Das XFS-Dateisystem verwendet stattdessen einen B + -Baum . Dies hat gegenüber einer Hash-Tabelle oder einem B-Baum den Vorteil, dass jeder Knoten mehrere untergeordnete Knoten b haben kann , wobei XFS b unterschiedlich ist und bis zu 254 (oder 19 für den Stammknoten) betragen kann. Diese Nummern sind möglicherweise veraltet ). Dies gibt Ihnen eine zeitliche Komplexität von O (log b n) , eine enorme Verbesserung.

Jedes dieser Dateisysteme kann Zehntausende von Dateien in einem einzigen Verzeichnis verarbeiten, wobei XFS in einem Verzeichnis mit der gleichen Anzahl von Inodes erheblich schneller ist als ext4. Aber Sie möchten wahrscheinlich kein einziges Verzeichnis mit 3M-Inodes, da die Suche selbst bei einem B + -Baum einige Zeit in Anspruch nehmen kann. Dies hat in erster Linie dazu geführt, dass Verzeichnisse auf diese Weise erstellt wurden.

Die erste Option, die Sie für Ihre vorgeschlagenen Strukturen angegeben haben, ist genau das, was in nginx-Beispielen gezeigt wird. Es funktioniert auf beiden Dateisystemen gut, obwohl XFS immer noch einen gewissen Vorteil bietet. Die zweite Option kann etwas besser oder etwas schlechter abschneiden, wird aber wahrscheinlich auch bei Benchmarks ziemlich knapp sein.

Michael Hampton
quelle
Und für XFS oder ext4 hat die Hardware, auf der Sie das Dateisystem installieren, enorme Auswirkungen auf die Leistung. Ein langsames SATA-Laufwerk mit 5.400 U / min kann ungefähr 50 zufällige E / A-Vorgänge pro Sekunde ausführen, ein gutes SAS-Laufwerk mit 15.000 U / min kann einige hundert Vorgänge ausführen, und eine SSD ist wahrscheinlich bandbreitenbeschränkt und kann einige Millionen zufällige E / A-Vorgänge pro Sekunde ausführen wenn nicht mehr.
Andrew Henle
1
Genau genommen ist $ O (\ log_b n) $ für festes $ b $ genauso komplex wie $ O (\ log n) $. Aber für das OP wären die tatsächlichen Konstanten von Bedeutung.
Hagen von Eitzen
Sofern mit meinem Dateisystem nichts nicht in Ordnung ist, kann ext4 nicht 10.000 Dateien in einem einzigen Verzeichnis verarbeiten. Das Ausführen eines einfachen Vorgangs ls -ldauert eine ganze Minute, wenn das Verzeichnis aus dem Inode-Cache entfernt wurde. Und wenn es zwischengespeichert wird, dauert es immer noch über eine Sekunde. Dies ist mit einer SSD und einem Xeon mit Tonnen von RAM auf einem ziemlich verkehrsarmen Webserver.
Abhi Beckert
@AbhiBeckert Wurde ein Upgrade von ext3 durchgeführt? Wenn ja, erstellen Sie ein neues Verzeichnis und verschieben Sie die Dateien dorthin.
Michael Hampton
@Hampton Nein. Es ist ein (ziemlich) kürzlich eingerichteter Server auf moderner Hardware. Ich arbeite seit ein paar Monaten an dem Problem mit unserem Systemadministrator / Rechenzentrum. Wir zahlen monatlich Tausende von Dollar, um den Server zu leasen und keine akzeptable Leistung zu erzielen. Es sieht so aus, als ob die einzige Möglichkeit darin besteht, in eine neue Verzeichnisstruktur zu wechseln - möglicherweise mithilfe von Hashes anstelle von Datumsangaben für Dateinamen, um sie gleichmäßiger zu verteilen.
Abhi Beckert
5

Nach meiner Erfahrung ist einer der Skalierungsfaktoren die Größe der Inodes bei einer Partitionierungsstrategie für Hash-Namen.

Beide von Ihnen vorgeschlagenen Optionen erstellen bis zu drei Inode-Einträge für jede erstellte Datei. Außerdem erzeugen 732-Dateien einen Inode, der immer noch kleiner als die üblichen 16 KB ist. Für mich bedeutet dies, dass beide Optionen die gleiche Leistung erbringen.

Ich begrüße Sie für Ihren kurzen Haschisch. Bei früheren Systemen, an denen ich gearbeitet habe, wurde die Summe der angegebenen Dateien und der gespleißten Verzeichnisse basierend auf dieser Zeichenfolge verwendet. Dies ist ein weitaus schwierigeres Problem.

sysadmin1138
quelle
1
Was macht die Verwendung von SHA1-Summen (und anderen längeren Hash-Summen) "zu einem viel schwierigeren Problem"? Es ist zwar für menschliche Benutzer unhandlich, aber für das Betriebssystem, das Dateisystem und andere Programme gleich.
kbolino
4

Mit beiden Optionen können Sie die Anzahl der Dateien in einem Verzeichnis auf einen Wert reduzieren, der für xfs, ext4 oder ein anderes Dateisystem als sinnvoll erscheint. Es ist nicht klar, was besser ist, müsste testen, um zu sagen.

Ein Benchmark mit Ihrer Anwendung, die so etwas wie die tatsächliche Arbeitslast simuliert, ist ideal. Andernfalls lassen Sie sich etwas einfallen, das viele kleine Dateien speziell simuliert. Apropos, hier ist eine Open-Source-Datei namens Smallfile . Die Dokumentation verweist auf einige andere Tools.

hdparmDauerhafte E / A-Vorgänge sind weniger nützlich. Es werden nicht die vielen kleinen E / A-Vorgänge oder riesigen Verzeichniseinträge angezeigt, die mit sehr vielen Dateien verknüpft sind.

John Mahowald
quelle
1

Eines der Probleme ist die Möglichkeit, den Ordner zu scannen.

Stellen Sie sich eine Java-Methode vor, die einen Scan für den Ordner ausführt.

Es muss eine große Menge an Speicher reservieren und diese in kurzer Zeit freigeben, was für die JVM sehr schwer ist.

Am besten ordnen Sie die Ordnerstruktur so an, dass sich jede Datei in einem bestimmten Ordner befindet, z. B. Jahr / Monat / Tag.

Bei einem vollständigen Scan wird für jeden Ordner eine Ausführung der Funktion ausgeführt, sodass JVM die Funktion beendet, den Arbeitsspeicher freigibt und ihn erneut für einen anderen Ordner ausführt.

Dies ist nur ein Beispiel, aber es macht sowieso keinen Sinn, solch einen riesigen Ordner zu haben.

Andrew Smith
quelle
2
Sie setzen Java voraus und scannen den Ordner. Beides wird in der Frage nicht erwähnt, und es gibt andere Möglichkeiten, den Ordner in Java zu verarbeiten, als ihn zu scannen.
user207421
1

Ich habe das gleiche Problem gehabt. Versucht, Millionen von Dateien auf einem Ubuntu-Server in ext4 zu speichern. Ich habe damit aufgehört, meine eigenen Benchmarks zu erstellen. Stellen Sie fest, dass Flat Directory eine bessere Leistung erbringt und gleichzeitig einfacher zu bedienen ist:

Benchmark

Schrieb einen Artikel .

Hartator
quelle
Das ist definitiv nicht das erwartete Ergebnis. Bevor Sie dies tun oder empfehlen, sollten Sie sich genauer ansehen, warum Sie dieses unerwartete Ergebnis erzielt haben.
Michael Hampton