Speichern Sie effizient Hunderte Millionen kleiner Dateien. Selbstgehostete Lösung

Speichern Sie effizient Hunderte Millionen kleiner Dateien. Selbstgehostete Lösung

Liebe Community, dieser Artikel konzentriert sich auf das effiziente Speichern und Abrufen von Hunderten Millionen kleiner Dateien. Zu diesem Zeitpunkt wird die endgültige Lösung für POSIX-kompatible Dateisysteme mit vollständiger Unterstützung für Sperren, einschließlich Cluster-Sperren, und scheinbar sogar ohne Krücken vorgeschlagen.

Deshalb habe ich zu diesem Zweck meinen eigenen benutzerdefinierten Server geschrieben.
Im Zuge der Umsetzung dieser Aufgabe ist es uns gelungen, das Hauptproblem zu lösen und gleichzeitig Speicherplatz und RAM einzusparen, die unser Cluster-Dateisystem gnadenlos beanspruchte. Tatsächlich ist eine solche Anzahl von Dateien schädlich für jedes geclusterte Dateisystem.

Die Idee ist diese:

Mit einfachen Worten: Kleine Dateien werden über den Server hochgeladen, direkt im Archiv gespeichert und auch daraus gelesen, und große Dateien werden nebeneinander abgelegt. Schema: 1 Ordner = 1 Archiv, insgesamt haben wir mehrere Millionen Archive mit kleinen Dateien und nicht mehrere hundert Millionen Dateien. Und das alles ist vollständig implementiert, ohne Skripte oder das Ablegen von Dateien in TAR/ZIP-Archiven.

Ich werde versuchen, mich kurz zu fassen. Ich entschuldige mich im Voraus, falls der Beitrag zu lang ist.

Alles begann damit, dass ich weltweit keinen geeigneten Server finden konnte, der über das HTTP-Protokoll empfangene Daten direkt in Archiven speichern konnte, ohne die Nachteile herkömmlicher Archive und Objektspeicher. Und der Grund für die Suche war der stark angewachsene Origin-Cluster aus 10 Servern, in dem sich bereits 250,000,000 kleine Dateien angesammelt hatten und der Wachstumstrend nicht aufhören wollte.

Für diejenigen, die nicht gerne Artikel lesen, ist eine kleine Dokumentation einfacher:

hierher и hierher.

Und Docker gleichzeitig, jetzt gibt es für alle Fälle eine Option nur mit Nginx darin:

docker run -d --restart=always -e host=localhost -e root=/var/storage 
-v /var/storage:/var/storage --name wzd -p 80:80 eltaline/wzd

Next:

Wenn viele Dateien vorhanden sind, werden erhebliche Ressourcen benötigt, und das Schlimmste ist, dass einige davon verschwendet werden. Wenn Sie beispielsweise ein geclustertes Dateisystem (in diesem Fall MooseFS) verwenden, nimmt die Datei unabhängig von ihrer tatsächlichen Größe immer mindestens 64 KB ein. Das heißt, für Dateien mit einer Größe von 3, 10 oder 30 KB sind 64 KB auf der Festplatte erforderlich. Bei einer Viertelmilliarde Dateien verlieren wir 2 bis 10 Terabyte. Es wird nicht möglich sein, auf unbestimmte Zeit neue Dateien zu erstellen, da MooseFS eine Einschränkung hat: nicht mehr als 1 Milliarde mit einer Replik jeder Datei.

Mit steigender Dateianzahl wird viel RAM für Metadaten benötigt. Auch häufige große Metadaten-Dumps tragen zur Abnutzung von SSD-Laufwerken bei.

wZD-Server. Wir bringen Ordnung auf die Datenträger.

Der Server ist in Go geschrieben. Zunächst musste ich die Anzahl der Dateien reduzieren. Wie kann man das machen? Aufgrund der Archivierung, in diesem Fall jedoch ohne Komprimierung, da es sich bei meinen Dateien lediglich um komprimierte Bilder handelt. Zur Rettung kam BoltDB, das noch seine Mängel beseitigen musste, was sich in der Dokumentation widerspiegelt.

Insgesamt waren in meinem Fall statt einer Viertelmilliarde Dateien nur noch 10 Millionen Bolt-Archive übrig. Wenn ich die Möglichkeit hätte, die aktuelle Verzeichnisdateistruktur zu ändern, wäre es möglich, sie auf etwa 1 Million Dateien zu reduzieren.

Alle kleinen Dateien werden in Bolt-Archive gepackt, die automatisch die Namen der Verzeichnisse erhalten, in denen sie sich befinden, und alle großen Dateien bleiben neben den Archiven; es macht keinen Sinn, sie zu packen, das ist anpassbar. Kleinere werden archiviert, große bleiben unverändert. Der Server arbeitet transparent mit beiden.

Architektur und Funktionen des wZD-Servers.

Speichern Sie effizient Hunderte Millionen kleiner Dateien. Selbstgehostete Lösung

Der Server läuft unter den Betriebssystemen Linux, BSD, Solaris und OSX. Ich habe nur die AMD64-Architektur unter Linux getestet, aber sie sollte für ARM64, PPC64, MIPS64 funktionieren.

Haupteigenschaften:

  • Multithreading;
  • Multiserver, der Fehlertoleranz und Lastausgleich bietet;
  • Maximale Transparenz für den Benutzer oder Entwickler;
  • Unterstützte HTTP-Methoden: GET, HEAD, PUT und DELETE;
  • Steuerung des Lese- und Schreibverhaltens über Client-Header;
  • Unterstützung für flexible virtuelle Hosts;
  • Unterstützung der CRC-Datenintegrität beim Schreiben/Lesen;
  • Halbdynamische Puffer für minimalen Speicherverbrauch und optimale Optimierung der Netzwerkleistung;
  • Verzögerte Datenkomprimierung;
  • Darüber hinaus wird ein Multithread-Archiver wZA zur Migration von Dateien ohne Unterbrechung des Dienstes angeboten.

Echte Erfahrung:

Ich habe den Server und den Archivierer schon seit geraumer Zeit entwickelt und anhand von Live-Daten getestet. Jetzt läuft er erfolgreich auf einem Cluster, der 250,000,000 kleine Dateien (Bilder) umfasst, die sich in 15,000,000 Verzeichnissen auf separaten SATA-Laufwerken befinden. Ein Cluster aus 10 Servern ist ein Origin-Server, der hinter einem CDN-Netzwerk installiert ist. Zur Wartung werden 2 Nginx-Server + 2 wZD-Server verwendet.

Für diejenigen, die sich für die Verwendung dieses Servers entscheiden, ist es ratsam, vor der Verwendung gegebenenfalls die Verzeichnisstruktur zu planen. Lassen Sie mich gleich einen Vorbehalt anbringen, dass der Server nicht dazu gedacht ist, alles in ein 1-Bolt-Archiv zu stopfen.

Leistungstest:

Je kleiner die komprimierte Datei ist, desto schneller werden GET- und PUT-Vorgänge darauf ausgeführt. Vergleichen wir die Gesamtzeit für das Schreiben des HTTP-Clients in reguläre Dateien und Bolt-Archive sowie für das Lesen. Verglichen wird die Arbeit mit Dateien der Größen 32 KB, 256 KB, 1024 KB, 4096 KB und 32768 KB.

Bei der Arbeit mit Bolt-Archiven wird die Datenintegrität jeder Datei überprüft (CRC wird verwendet), vor der Aufnahme und auch nach der Aufnahme erfolgt ein spontanes Lesen und eine Neuberechnung, was natürlich zu Verzögerungen führt, aber das Wichtigste ist die Datensicherheit.

Ich habe Leistungstests mit SSD-Laufwerken durchgeführt, da Tests mit SATA-Laufwerken keinen deutlichen Unterschied zeigen.

Diagramme basierend auf Testergebnissen:

Speichern Sie effizient Hunderte Millionen kleiner Dateien. Selbstgehostete Lösung
Speichern Sie effizient Hunderte Millionen kleiner Dateien. Selbstgehostete Lösung

Wie Sie sehen, ist der Unterschied in den Lese- und Schreibzeiten zwischen archivierten und nicht archivierten Dateien bei kleinen Dateien gering.

Ein völlig anderes Bild ergibt sich beim Testen des Lesens und Schreibens von Dateien mit einer Größe von 32 MB:

Speichern Sie effizient Hunderte Millionen kleiner Dateien. Selbstgehostete Lösung

Der Zeitunterschied zwischen dem Lesen von Dateien liegt zwischen 5 und 25 ms. Bei der Aufnahme sieht es noch schlimmer aus, der Unterschied beträgt etwa 150 ms. In diesem Fall besteht jedoch keine Notwendigkeit, große Dateien hochzuladen; es hat einfach keinen Sinn, dies zu tun; sie können getrennt von den Archiven leben.

*Technisch gesehen können Sie diesen Server für Aufgaben verwenden, die NoSQL erfordern.

Grundlegende Methoden zum Arbeiten mit dem wZD-Server:

Laden einer regulären Datei:

curl -X PUT --data-binary @test.jpg http://localhost/test/test.jpg

Hochladen einer Datei in das Bolt-Archiv (sofern der Serverparameter fmaxsize, der die maximale Dateigröße bestimmt, die in das Archiv aufgenommen werden kann, nicht überschritten wird; bei Überschreitung wird die Datei wie gewohnt neben dem Archiv hochgeladen):

curl -X PUT -H "Archive: 1" --data-binary @test.jpg http://localhost/test/test.jpg

Herunterladen einer Datei (wenn sich auf der Festplatte und im Archiv Dateien mit demselben Namen befinden, wird beim Herunterladen standardmäßig der nicht archivierten Datei Vorrang eingeräumt):

curl -o test.jpg http://localhost/test/test.jpg

Herunterladen einer Datei aus dem Bolt-Archiv (erzwungen):

curl -o test.jpg -H "FromArchive: 1" http://localhost/test/test.jpg

Beschreibungen anderer Methoden finden Sie in der Dokumentation.

wZD-Dokumentation
wZA-Dokumentation

Der Server unterstützt derzeit nur das HTTP-Protokoll, mit HTTPS funktioniert er noch nicht. Auch die POST-Methode wird nicht unterstützt (es ist noch nicht entschieden, ob sie benötigt wird oder nicht).

Wer sich in den Quellcode vertieft, wird dort Butterscotch finden, das gefällt nicht jedem, aber ich habe den Hauptcode bis auf den Interrupt-Handler nicht an die Funktionen des Web-Frameworks gebunden, sodass ich ihn in Zukunft für fast jeden schnell umschreiben kann Motor.

Machen:

  • Entwicklung eines eigenen Replikators und Verteilers + Geo für die Möglichkeit des Einsatzes in großen Systemen ohne Cluster-Dateisysteme (Alles für Erwachsene)
  • Möglichkeit der vollständigen umgekehrten Wiederherstellung von Metadaten, wenn diese vollständig verloren gehen (bei Verwendung eines Distributors)
  • Natives Protokoll für die Möglichkeit, dauerhafte Netzwerkverbindungen und Treiber für verschiedene Programmiersprachen zu nutzen
  • Erweiterte Möglichkeiten zur Nutzung der NoSQL-Komponente
  • Komprimierungen unterschiedlicher Art (gzip, zstd, snappy) für Dateien oder Werte in Bolt-Archiven und für reguläre Dateien
  • Verschlüsselung unterschiedlicher Art für Dateien oder Werte in Bolt-Archiven und für reguläre Dateien
  • Verzögerte serverseitige Videokonvertierung, auch auf der GPU

Ich habe alles, ich hoffe, dieser Server wird jemandem nützlich sein, BSD-3-Lizenz, doppeltes Urheberrecht, denn wenn es keine Firma gäbe, in der ich arbeite, wäre der Server nicht geschrieben worden. Ich bin der einzige Entwickler. Ich wäre dankbar für alle Fehler und Funktionswünsche, die Sie finden.

Source: habr.com

Kommentar hinzufügen