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:
-
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.
-
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.
-
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).
-
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.