11 Stimmen

Großflächige Bildspeicherung

Ich werde wahrscheinlich an einem Projekt beteiligt sein, bei dem eine wichtige Komponente ein Speicher für eine große Anzahl von Dateien ist (in diesem Fall Bilder, aber es sollte nur als Dateispeicher dienen).

Die Zahl der eingehenden Dateien dürfte bei etwa 500.000 pro Woche liegen (durchschnittlich etwa 100 KB pro Datei), mit Spitzenwerten von etwa 100.000 Dateien pro Tag und 5 pro Sekunde. Die Gesamtzahl der Dateien wird voraussichtlich mehrere zehn Millionen erreichen, bevor ein Gleichgewicht erreicht wird, bei dem die Dateien aus verschiedenen Gründen mit der Eingangsrate gelöscht werden.

Ich brauche also ein System, das in Spitzenzeiten etwa 5 Dateien pro Sekunde speichern kann, während ich jederzeit etwa 4 Dateien lesen und 4 löschen kann.

Meine ursprüngliche Idee ist, dass ein einfaches NTFS-Dateisystem mit einem einfachen Dienst zum Speichern, Ablaufen und Lesen eigentlich ausreichen sollte. Ich könnte mir vorstellen, dass der Dienst Unterordner für jedes Jahr, jeden Monat, jeden Tag und jede Stunde erstellt, um die Anzahl der Dateien pro Ordner auf ein Minimum zu beschränken und einen manuellen Ablauf zu ermöglichen, falls dies erforderlich sein sollte.

Eine große NTFS-Lösung wurde diskutiert ici Aber ich könnte trotzdem einen Rat gebrauchen, welche Probleme beim Bau eines Speichers mit den genannten Spezifikationen zu erwarten sind, welche Wartungsprobleme zu erwarten sind und welche Alternativen es gibt. Vorzugsweise möchte ich eine verteilte Speicherung vermeiden, wenn dies möglich und praktisch ist.

editar

Vielen Dank für die vielen Kommentare und Vorschläge. Noch ein paar zusätzliche Informationen über das Projekt:

Es handelt sich nicht um eine Webanwendung, bei der die Bilder von den Endnutzern bereitgestellt werden. Ohne zu viel verraten zu wollen: Da sich das Projekt in der Vertragsphase befindet, fällt es eher in die Kategorie der Qualitätskontrolle. Denken Sie an eine Produktionsanlage mit Förderband und Sensoren. Es handelt sich nicht um eine herkömmliche Qualitätskontrolle, da der Wert des Produkts vollständig vom reibungslosen Funktionieren der Bild- und Metadaten-Datenbank abhängt.

Der Zugriff auf die Bilder erfolgt zu 99 % durch eine autonome Anwendung in der Reihenfolge "first in - first out", aber auch der zufällige Zugriff durch eine Benutzeranwendung ist möglich. Bilder, die älter als ein Tag sind, werden hauptsächlich für Archivierungszwecke verwendet, obwohl auch dieser Zweck sehr wichtig ist.

Der Verfall der Bilder folgt aus verschiedenen Gründen komplexen Regeln, aber irgendwann sollten alle Bilder gelöscht werden. Die Löschungsregeln folgen einer Geschäftslogik, die von Metadaten und Benutzerinteraktionen abhängt.

Jeden Tag wird es Ausfallzeiten geben, in denen Wartungsarbeiten durchgeführt werden können.

Vorzugsweise muss der Dateispeicher den Standort des Bildes nicht an den Metadatenserver zurückmelden. Der Speicherort des Bildes sollte eindeutig aus den Metadaten abgeleitet werden, möglicherweise durch eine Zuordnungsdatenbank, wenn eine Art von Hashing oder ein verteiltes System gewählt wird.

Meine Fragen lauten also:

  • Welche Technologien sind geeignet, um eine solide Arbeit zu leisten?
  • Welche Technologien werden die geringsten Implementierungskosten haben?
  • Welche Technologien lassen sich von der IT-Abteilung des Kunden am einfachsten warten?
  • Welche Risiken gibt es für eine bestimmte Technologie in diesem Umfang (5-20 TB Daten, 10-100 Millionen Dateien)?

6voto

Matt Sieker Punkte 8669

Hier ein paar zufällige Überlegungen zur Umsetzung und zu möglichen Problemen, die auf folgenden Annahmen beruhen: durchschnittliche Bildgröße von 100 KB und ein Dauerzustand von 50 Mio. (5 GB) Bildern. Dabei wird auch davon ausgegangen, dass die Benutzer nicht direkt auf den Dateispeicher zugreifen, sondern dies über eine Software oder eine Website tun werden:

  1. Speichermedium: Die Größe der Bilder, die Sie angeben, ergibt eine eher mickrige Lese- und Schreibgeschwindigkeit, ich würde denken, dass die meisten gängigen Festplatten kein Problem mit diesem Durchsatz haben. Ich würde sie jedoch aus Gründen der Datensicherheit in eine RAID1-Konfiguration einbinden. Backups dürften kein allzu großes Problem darstellen, da es sich nur um 5 GB Daten handelt.

  2. Dateiablage: Um Probleme mit der maximalen Anzahl von Dateien in einem Verzeichnis zu vermeiden, würde ich den Hash nehmen (mindestens MD5), das wäre am schnellsten, aber am kollisionsanfälligsten. Und bevor jetzt jemand behauptet, MD5 sei kaputt, dies dient der Identifizierung und nicht der Sicherheit. Ein Angreifer könnte Bilder für einen zweiten Vorab-Angriff auffüllen und alle Bilder durch Ziegenkäse ersetzen, aber das halten wir für unwahrscheinlich), und diesen Hash in eine hexadezimale Zeichenfolge umwandeln. Wenn es dann an der Zeit ist, die Datei im Dateisystem zu speichern, nehmen Sie die hexadezimale Zeichenkette in Blöcken von 2 Zeichen und erstellen eine darauf basierende Verzeichnisstruktur für diese Datei. Wenn die Datei z.B. einen Hashwert von abcdef wäre das Root-Verzeichnis ab und darunter ein Verzeichnis namens cd , unter dem Sie das Bild mit dem Namen abcdef . Der echte Name wird an anderer Stelle gespeichert (siehe unten).

    Wenn Sie bei diesem Ansatz wegen zu vieler Dateien in einem Verzeichnis an die Grenzen des Dateisystems (oder an Leistungsprobleme) stoßen, können Sie den Dateispeicherteil einfach eine weitere Ebene von Verzeichnissen anlegen lassen. Sie könnten auch in den Metadaten speichern, auf wie vielen Verzeichnisebenen die Datei erstellt wurde, so dass bei einer späteren Erweiterung ältere Dateien nicht in den neueren, tieferen Verzeichnissen gesucht werden.

    Dies ist ein weiterer Vorteil: Wenn Sie Probleme mit der Übertragungsgeschwindigkeit oder mit dem Dateisystem im Allgemeinen haben, können Sie eine Reihe von Dateien einfach auf andere Laufwerke verteilen. Ändern Sie einfach die Software so, dass die Verzeichnisse der obersten Ebene auf verschiedenen Laufwerken liegen. Wenn Sie also den Speicher in zwei Hälften aufteilen wollen, 00-7F auf einem Laufwerk, 80-FF auf einem anderen.

    Durch das Hashing erhalten Sie auch Speicherplatz für eine einzelne Instanz, was sehr nützlich sein kann. Da Hashes einer normalen Population von Dateien dazu neigen, zufällig zu sein, sollte dies auch zu einer gleichmäßigen Verteilung der Dateien über alle Verzeichnisse führen.

  3. Speicherung von Metadaten: 50 Mio. Zeilen scheinen zwar viel zu sein, aber die meisten DBMS sind für eine solche Anzahl von Datensätzen ausgelegt, natürlich mit genügend RAM. Die folgenden Ausführungen basieren auf SQL Server, aber ich bin sicher, dass das meiste davon auch für andere Systeme gilt. Erstellen Sie eine Tabelle mit dem Hash der Datei als Primärschlüssel sowie Angaben zu Größe, Format und Verschachtelungsebene. Erstellen Sie dann eine weitere Tabelle mit einem künstlichen Schlüssel (eine int-Identitätsspalte wäre hierfür gut geeignet) und dem ursprünglichen Namen der Datei (varchar(255) oder wie auch immer) sowie dem Hash als Fremdschlüssel zurück zur ersten Tabelle und dem Datum, an dem er hinzugefügt wurde, mit einem Index auf der Dateinamensspalte. Fügen Sie auch alle anderen Spalten hinzu, die Sie benötigen, um festzustellen, ob eine Datei abgelaufen ist oder nicht. Auf diese Weise können Sie den ursprünglichen Namen speichern, wenn mehrere Personen versuchen, dieselbe Datei unter verschiedenen Namen hinzuzufügen (die aber ansonsten identisch sind, da sie denselben Hash haben).

  4. Wartung: Dies sollte eine geplante Aufgabe sein. Überlassen Sie es Windows, sich darum zu kümmern, wann Ihre Aufgabe ausgeführt wird, damit Sie weniger Probleme mit der Fehlersuche haben (was wäre, wenn Sie die Wartung jede Nacht um 2:30 Uhr durchführen und Sie sich an einem Ort befinden, der die Sommerzeit einhält? 2:30 Uhr findet während der Frühjahrsumstellung nicht statt). Dieser Dienst führt dann eine Abfrage in der Datenbank durch, um festzustellen, welche Dateien abgelaufen sind (auf der Grundlage der pro Dateiname gespeicherten Daten, damit er weiß, wann alle Verweise auf eine gespeicherte Datei abgelaufen sind). Jede gehashte Datei, auf die nicht mindestens eine Zeile in der Dateinamen-Tabelle verweist, wird nicht mehr benötigt). Der Dienst würde dann diese Dateien löschen.

Ich denke, das war's dann auch schon mit den wichtigsten Teilen.

EDIT: Mein Kommentar wurde zu lang, ich verschiebe ihn in ein Edit:

Ups, mein Fehler, das kommt davon, wenn ich müde bin und rechne. In diesem Fall, wenn Sie die zusätzliche Redundanz des Hinzufügens von RAID-Levels (51 oder 61 z.B. gespiegelt über einen Striped-Satz) vermeiden wollen, hätte das Hashing den Vorteil, dass Sie 5 1TB-Laufwerke in den Server einstecken können und dann die Dateispeichersoftware die Laufwerke nach dem Hash aufspannen lässt, wie am Ende von 2 erwähnt. Sie könnten die Laufwerke für zusätzliche Sicherheit sogar RAID1 machen.

Die Sicherung wäre komplizierter, obwohl die Erstellungs- und Änderungszeiten des Dateisystems immer noch dafür gelten würden (Sie könnten jede Datei berühren, um ihre Änderungszeit zu aktualisieren, wenn eine neue Referenz zu dieser Datei hinzugefügt wird).

Ich sehe einen doppelten Nachteil darin, bei den Verzeichnissen nach Datum/Uhrzeit vorzugehen. Erstens ist es unwahrscheinlich, dass die Verteilung gleichmäßig ist, was dazu führt, dass einige Verzeichnisse voller sind als andere. Hashing würde eine gleichmäßige Verteilung bewirken. Was das Verteilen angeht, so könnte man den Speicherplatz auf dem Laufwerk überwachen, während man Dateien hinzufügt, und auf das nächste Laufwerk auslagern, wenn der Platz knapp wird. Ich könnte mir vorstellen, dass ein Teil des Ablaufs mit dem Datum zusammenhängt, so dass ältere Laufwerke beginnen, sich zu leeren, während sich neuere füllen, und man müsste herausfinden, wie man das ausgleichen kann.

Der Metadatenspeicher muss sich nicht auf dem Server selbst befinden. Sie speichern bereits dateibezogene Daten in der Datenbank. Anstatt den Pfad direkt in der Zeile zu referenzieren, in der er verwendet wird, verweisen Sie stattdessen auf den Dateinamenschlüssel (die zweite Tabelle, die ich erwähnt habe).

Ich stelle mir vor, dass die Benutzer eine Art Web oder eine Anwendung als Schnittstelle zum Speicher verwenden, so dass die Intelligenz, um herauszufinden, wo die Datei auf dem Speicherserver abgelegt werden soll, dort vorhanden ist und einfach die Wurzeln der Laufwerke verteilt werden (oder man macht etwas Ausgefallenes mit NTFS-Junctioning, um alle Laufwerke in ein Unterverzeichnis zu legen). Wenn Sie erwarten, eine Datei über eine Website abzurufen, erstellen Sie eine Seite auf der Website, die die Dateinamen-ID nimmt, dann führen Sie die Suche in der DB durch, um den Hash zu erhalten, dann würde der Hash auf eine beliebige konfigurierte Ebene zerlegt und über die Freigabe an den Server angefordert und dann zurück an den Client gestreamt. Wenn ein UNC für den Zugriff auf die Datei erwartet wird, sollte der Server stattdessen einfach den UNC erstellen.

Beide Methoden machen Ihre Endbenutzeranwendung weniger abhängig von der Struktur des Dateisystems selbst und erleichtern Ihnen die spätere Anpassung und Erweiterung Ihres Speichers.

3voto

Samuel Neff Punkte 70231

Speichern Sie die Bilder in einer Reihe von SQLite-Datenbanken. Klingt zunächst verrückt, ist aber wirklich schneller als die direkte Speicherung im Dateisystem und nimmt weniger Platz ein.

SQLite ist äußerst effizient bei der Speicherung von Binärdaten, und durch die Speicherung der Dateien in einer aggregierten Datenbank anstelle von einzelnen Betriebssystemdateien wird Overhead eingespart, wenn die Bilder nicht in exakte Blockgrößen passen (was bei so vielen Dateien erheblich ist). Außerdem können die ausgelagerten Daten in SQLite zu einem schnelleren Durchsatz führen als bei einfachen Betriebssystemdateien.

SQLite hat Gleichzeitigkeitsbeschränkungen bei Schreibvorgängen, die jedoch innerhalb der von Ihnen genannten Grenzen liegen und durch den geschickten Einsatz mehrerer (hunderter) SQLite-Datenbanken noch weiter gemildert werden können.

Probieren Sie es aus, Sie werden angenehm überrascht sein.

2voto

Dies sind nur ein paar Vorschläge, die auf den hier gegebenen allgemeinen Informationen beruhen, ohne dass Sie genau wissen, was Ihre Anwendung tatsächlich tut oder tun wird.

  • sha1 der Datei als Dateiname verwenden (bei Bedarf den vom Benutzer eingegebenen Dateinamen in der DB speichern)

    Die Sache ist die, dass man, wenn man sich um die Daten kümmert, sowieso eine Prüfsumme speichern muss.
    Wenn Sie sha1 (sha256, md5 oder einen anderen Hash) verwenden, ist es einfach, die Dateidaten zu überprüfen - lesen Datei, cacl-Hash, wenn er mit dem Namen übereinstimmt, sind die Daten gültig. Angenommen, dies ist eine Webapplikation ist, kann der Hash-basierte Dateiname als Etag beim Ausliefern der Daten verwendet werden. (Schauen Sie in Ihrem .git-Verzeichnis nach einem Beispiel dafür). Dies setzt voraus, dass Sie nicht vom Benutzer angegebenen Dateinamen nicht verwenden können, da der Benutzer etwas wie "<>?:().txt" senden kann.

  • Verwenden Sie eine Verzeichnisstruktur, die aus Sicht Ihrer Anwendung sinnvoll ist.

    Der Haupttest besteht darin, dass es möglich sein sollte, eine Datei allein durch einen Blick auf die auf PATH \FILE allein, ohne die Metadaten in der DB zu suchen. Wenn Ihre Speicher-/Zugriffsmuster streng zeitbasiert sind, dann ist STORE \DATE\HH\FILE wäre sinnvoll, wenn Sie Dateien haben, die Benutzern gehören, dann vielleicht STORE\<1. N Ziffern der UID> \UID\FILE Sinn machen würde.

  • Transaktionen für Datei-/Metadatenoperationen verwenden

    d.h. start write file metadata trx, versuche eine Datei in FS zu schreiben, bei Erfolg commit trx, rollback bei Fehler. Es sollte mit äußerster Sorgfalt vorgegangen werden, um zu vermeiden, dass Sie Dateimetadaten in der DB und keine Datei im FS haben und umgekehrt.

  • mehrere Root-Speicherplätze verwenden

    d.h. STORE01\ STORE02\ STORE\ - dies kann bei der Entwicklung (und später bei der Skalierung) helfen. Es ist möglich, dass mehrere Entwickler einen zentralen DB- und Dateispeicher verwenden, der lokal auf ihrem Rechner liegt. Die Verwendung von STORE von Anfang an hilft, eine Situation zu vermeiden, in der Metadaten/Dateikombinationen in einer Instanz einer Anwendung gültig sind, in der anderen aber nicht.

  • niemals absolute PATHs in DB speichern

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X