Effiziente Speicherung von Hunderten Millionen kleiner Dateien. Selbst gehostete Lösung



Liebe Community, dieser Artikel befasst sich mit der effizienten Speicherung und Bereitstellung von Hunderten Millionen kleiner Dateien. In dieser Phase wird die endgültige Lösung für POSIX-kompatible Dateisysteme mit vollständiger Unterstützung für Sperren, einschließlich Cluster-Dateisysteme und sogar ohne Krücken, vorgeschlagen.

Deshalb habe ich zu diesem Zweck meinen eigenen spezialisierten Server geschrieben.
Während dieser Aufgabe konnte das Hauptproblem gelöst werden, indem Speicherplatz und RAM gespart wurden, die unser Cluster-Dateisystem gnadenlos verbrauchte. Tatsächlich ist eine solche Anzahl von Dateien für jedes Cluster-Dateisystem schädlich.

Die Idee ist folgende:

Mit einfachen Worten, kleine Dateien werden über den Server hochgeladen, sie werden direkt im Archiv gespeichert und auch daraus gelesen, und große Dateien werden in der Nähe abgelegt. Schema: 1 Ordner = 1 Archiv, insgesamt haben wir mehrere Millionen Archive mit kleinen Dateien und nicht mehrere hundert Millionen Dateien. Und all dies ist vollständig implementiert, ohne Skripte und Dateizerlegung in tar / zip-Archiven.

Ich werde versuchen, es kürzer zu machen, ich entschuldige mich im Voraus, wenn der Beitrag groß sein wird.

Alles begann mit der Tatsache, dass ich keinen geeigneten Server auf der Welt finden konnte, der über das HTTP-Protokoll empfangene Daten direkt in Archiven speichern konnte, sodass normale Archive und Objekt-Repositorys keine Nachteile aufwiesen. Und der Grund für die Suche war ein Cluster von 10 Servern, die zu einem großen Origin gewachsen waren, in dem sich bereits 250.000.000 kleine Dateien angesammelt hatten und der Wachstumstrend nicht aufhören würde.

Diejenigen, die Artikel und ein wenig Dokumentation nicht gerne lesen, haben es leichter:

hier und hier .

Update Nginx aus Docker-Image entfernt.

Und Docker zur gleichen Zeit:
docker run -d --restart=always -e bindaddr=127.0.0.1:9699 \ -e host=localhost -e root=/var/storage -v /var/storage:/var/storage --name wzd \ -p 80:9699 eltaline/wzd 

Weiter:

Update In Version 1.1.0 wurde bereits die HTTPS / POST / IP-Authentifizierungsmethode usw. angezeigt.

Wenn es viele Dateien gibt, werden erhebliche Ressourcen benötigt, und am offensivsten ist, dass einige davon verschwendet werden. Wenn Sie beispielsweise ein Cluster-Dateisystem (in diesem Fall MooseFS) verwenden, benötigt eine Datei unabhängig von der tatsächlichen Größe immer mindestens 64 KB. 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 ist nicht möglich, unbegrenzt neue Dateien zu erstellen, da MooseFS selbst eine Einschränkung aufweist: nicht mehr als 1 Milliarde mit einem Replikat jeder Datei.

Wenn die Anzahl der Dateien zunimmt, benötigen Sie viel RAM für Metadaten. Häufige große Metadaten-Dumps tragen auch zum Verschleiß von SSDs bei.

WZD-Server. Wir bringen die Scheiben in Ordnung.

Der Server ist in Go geschrieben. Zunächst musste ich die Anzahl der Dateien reduzieren. Wie kann man das machen? Aufgrund der Archivierung, aber in diesem Fall ohne Komprimierung, da meine Dateien solide, beschnittene Bilder sind. Zur Rettung kam BoltDB, dem noch Mängel vorenthalten werden mussten, was sich in der Dokumentation widerspiegelt.

Insgesamt blieben statt einer Viertelmilliarde Akten in meinem Fall nur 10 Millionen Bolt-Archive übrig. Wenn ich die Möglichkeit hätte, die aktuelle Struktur des Füllens von Verzeichnisdateien zu ändern, wäre es möglich, auf ungefähr 1 Million Dateien zu reduzieren.

Alle kleinen Dateien werden in Bolt-Archive gepackt und erhalten automatisch die Namen der Verzeichnisse, in denen sie sich befinden. Alle großen Dateien verbleiben neben Archiven. Es macht keinen Sinn, sie zu packen. Dies ist anpassbar. Klein - Archiv, groß - unverändert lassen. Der Server arbeitet transparent mit beiden.

Architektur und Funktionen des wZD-Servers.



Auf dem Server werden Linux, BSD, Solaris und OSX ausgeführt. Ich habe nur die AMD64-Architektur unter Linux getestet, aber sie sollte auch für ARM64, PPC64 und MIPS64 geeignet sein.

Hauptmerkmale:

  • Multithreading;
  • Multi-Server, bietet Fehlertoleranz und Lastausgleich;
  • Maximale Transparenz für den Benutzer oder Entwickler;
  • Unterstützte HTTP-Methoden: GET, HEAD, PUT und DELETE;
  • Verwaltung des Lese- und Schreibverhaltens über Client-Header;
  • Unterstützung für anpassbare virtuelle Hosts;
  • Unterstützung der CRC-Datenintegrität beim Schreiben / Lesen;
  • Semidynamische Puffer für minimalen Speicherverbrauch und optimale Abstimmung der Netzwerkleistung;
  • Verzögerte Datenkomprimierung
  • Darüber hinaus wird ein Multithread-wZA-Archivierungsprogramm für die Dateimigration angeboten, ohne den Dienst zu beenden.

Echte Erfahrung:

Ich habe den Server und den Archivierer lange Zeit auf Live-Daten entwickelt und getestet. Jetzt funktioniert er erfolgreich in einem Cluster mit 250.000.000 kleinen Dateien (Bildern), die sich in 15.000.000 Verzeichnissen auf separaten SATA-Festplatten befinden. Ein Cluster von 10 Servern ist ein Origin-Server, der hinter einem CDN-Netzwerk installiert ist. Für die Wartung werden 2 Nginx-Server + 2 wZD-Server verwendet.

Für diejenigen, die sich für diesen Server entscheiden, ist es sinnvoll, die Verzeichnisstruktur gegebenenfalls vor der Verwendung zu planen. Machen Sie sofort eine Reservierung, dass der Server nicht dafür ausgelegt ist, alles in das 1-Bolt-Archiv zu verschieben.

Leistungstests:

Je kleiner die archivierte Datei ist, desto schneller werden die Operationen GET und PUT ausgeführt. Vergleichen Sie die Gesamtzeit, die der HTTP-Client in reguläre Dateien und in Bolt-Archive schreibt und auch liest. Es vergleicht die Arbeit mit Dateien mit einer Größe von 32 KB, 256 KB, 1024 KB, 4096 KB und 32768 KB.

Bei der Arbeit mit Bolt-Archiven wird die Integrität der Daten jeder Datei überprüft (CRC wird verwendet). Vor dem Schreiben und auch nach dem Schreiben wird im laufenden Betrieb gelesen und nachgezählt. Dies führt natürlich zu Verzögerungen. Hauptsache ist jedoch die Datensicherheit.

Ich habe Leistungstests auf SSDs durchgeführt, da die Tests auf SATA-Festplatten keinen deutlichen Unterschied zeigen.

Update (v1.1.0), verbesserte Leistung um 5-25%.

Diagramme basierend auf Testergebnissen:




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

Beim Lesen und Schreiben von 32-MB-Dateien erhalten wir ein völlig anderes Bild:



Der Zeitunterschied zwischen dem Lesen von Dateien liegt zwischen 5 und 25 ms. Bei der Aufnahme sieht es noch schlimmer aus, die Differenz beträgt ca. 150 ms. In diesem Fall ist es jedoch nicht erforderlich, große Dateien hochzuladen. Dies ist einfach nicht sinnvoll. Sie können getrennt von Archiven gespeichert werden.

* Technisch gesehen kann dieser Server auch für Aufgaben verwendet werden, die NoSQL erfordern.

Grundlegende Methoden zum Arbeiten mit dem wZD-Server:

Laden Sie die reguläre Datei herunter:
 curl -X PUT --data-binary @test.jpg http://localhost/test/test.jpg 

Hochladen einer Datei in das Bolt-Archiv (wenn der Serverparameter fmaxsize nicht überschritten wird, der die maximale Dateigröße festlegt, die in das Archiv aufgenommen werden kann, wird die Datei bei Überschreitung wie gewohnt neben dem Archiv geladen):
 curl -X PUT -H "Archive: 1" --data-binary @test.jpg http://localhost/test/test.jpg 

Herunterladen einer Datei (wenn sich Dateien mit demselben Namen auf der Festplatte und im Archiv befinden, wird beim Herunterladen der entpackten Datei die Standardpriorität zugewiesen):
 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 


Eine Beschreibung anderer Methoden finden Sie in der Dokumentation.

WZD-Dokumentation
WZA-Dokumentation

Der Server unterstützt bisher nur HTTP, es funktioniert noch nicht mit HTTPS. Die POST-Methode wird ebenfalls nicht unterstützt (es wurde noch nicht entschieden, ob sie benötigt wird oder nicht).

Wer sich mit dem Quellcode befasst, findet dort ein Toffee, das nicht jeder mag, aber ich habe den Hauptcode bis auf den Interrupt-Handler nicht an die Funktionen des Webframeworks gebunden, damit ich in Zukunft schnell auf fast jede Engine umschreiben kann.

ToDo:

  • Entwicklung eines eigenen Replikators und Distributors + Geo für den Einsatz in großen Systemen ohne Cluster-FSs (alle für Erwachsene)
  • Die Möglichkeit, die Wiederherstellung von Metadaten vollständig rückgängig zu machen, wenn diese vollständig verloren gehen (wenn ein Verteiler verwendet wird)
  • Natives Protokoll für die Möglichkeit, permanente Netzwerkverbindungen und Treiber für verschiedene Programmiersprachen zu verwenden
  • Erweiterte Funktionen zur Verwendung der NoSQL-Komponente
  • Komprimierungen verschiedener Typen (gzip, zstd, snappy) für Dateien oder Werte in Bolt-Archiven und für normale Dateien
  • Verschiedene Verschlüsselungstypen für Dateien oder Werte in Bolt-Archiven und für normale Dateien
  • Verzögerte Server-Videokonvertierung, einschließlich GPU

Das ist alles, ich hoffe, dieser Server ist für jemanden nützlich, BSD-3-Lizenz, doppelte Urheberrechte, da es kein Unternehmen gibt, in dem ich arbeite, würde ich auch keinen Server schreiben. Ich bin ein Entwickler im Singular. Ich wäre dankbar für die gefundenen Bugs und Feature Requests.

Source: https://habr.com/ru/post/de484312/


All Articles