Ich habe eine Website, auf der Benutzerprofilbilder gespeichert werden. Jedes Bild wird in einem benutzerspezifischen Verzeichnis (Linux) gespeichert. Derzeit habe ich einen Kundenstamm von mehr als 30, was bedeutet, dass ich mehr als 30 Ordner haben werde. Meine aktuelle Linux-Box (ext2 / ext3) unterstützt jedoch nicht das Erstellen von mehr als 32000 Verzeichnissen. Wie komme ich daran vorbei? Sogar YouTube-Leute haben das gleiche Problem mit Video-Thumbnails. Aber sie haben es gelöst, indem sie zu ReiserFS gewechselt sind. Können wir keine bessere Lösung haben?
Update: Auf die Frage im IRC wurde nach einem Upgrade auf ext4 gefragt, das ein Limit von 64.000 hat, und natürlich können Sie auch darüber hinwegkommen . Oder Kernel-Hacking, um das Limit zu ändern.
Update: Wie wäre es, wenn Sie die Benutzerbasis basierend auf dem Benutzer-ID-Bereich in Ordner aufteilen. Das bedeutet 1-1000 in einem Ordner, 1000-2000 in dem anderen. Das scheint einfach zu sein. Was sagst du, Leute?
Ehrlich gesagt, gibt es keinen anderen Weg?
quelle
Antworten:
Diese Begrenzung gilt pro Verzeichnis und nicht für das gesamte Dateisystem. Sie können sie also umgehen, indem Sie die Dinge weiter unterteilen. Anstatt beispielsweise alle Benutzer-Unterverzeichnisse im selben Verzeichnis zu haben, teilen Sie sie nach den ersten beiden Zeichen des Namens auf, sodass Sie Folgendes haben:
Noch besser wäre es, eine Art Hash der Namen zu erstellen und diesen für die Division zu verwenden. Auf diese Weise erhalten Sie eine bessere Verteilung auf die Verzeichnisse, anstatt im Beispiel der Anfangsbuchstaben "da" sehr voll und "zz" vollständig leer zu sein. Wenn Sie beispielsweise den Namen CRC oder MD5 verwenden und die ersten 8 Bits verwenden, erhalten Sie Folgendes:
Dies kann nach Bedarf auf weitere Tiefen erweitert werden, z. B. wenn der Benutzername kein Hashwert ist:
Diese Methode wird an vielen Stellen verwendet, z. B. im Squid-Cache, um Ludwigs Beispiel zu kopieren, und in den lokalen Caches von Webbrowsern.
Eine wichtige Sache, die Sie beachten sollten, ist, dass Sie mit ext2 / 3 auf Leistungsprobleme stoßen, bevor Sie sich ohnehin dem Grenzwert von 32.000 nähern, da Verzeichnisse linear durchsucht werden. Durch das Verschieben in ein anderes Dateisystem (z. B. ext4 oder reiser) wird diese Ineffizienz beseitigt (reiser durchsucht Verzeichnisse mit einem binär aufgeteilten Algorithmus, damit lange Verzeichnisse viel effizienter verarbeitet werden, ext4 kann dies auch tun) sowie das feste Limit pro Verzeichnis.
quelle
Wenn Sie an ext2 / ext3 gebunden sind, besteht die einzige Möglichkeit, die ich sehe, darin, Ihre Daten zu partitionieren. Suchen Sie ein Kriterium, das Ihre Daten in verwaltbare Blöcke ähnlicher Größe aufteilt.
Wenn es nur um die Profilbilder geht, würde ich Folgendes tun:
Der SQUID-Cache macht es beispielsweise so:
f / 4b / 353ac7303854033
Das Verzeichnis der obersten Ebene ist die erste Hex-Ziffer, die zweite Ebene die nächsten beiden Hex-Ziffern und der Dateiname die verbleibenden Hex-Ziffern.
quelle
Sie haben eine bessere Lösung - verwenden Sie ein anderes Dateisystem, es stehen zahlreiche zur Verfügung, von denen viele für verschiedene Aufgaben optimiert sind. Wie Sie bereits betont haben, ist ReiserFS für die Verarbeitung vieler Dateien in einem Verzeichnis optimiert.
Hier finden Sie einen Vergleich der Dateisysteme.
Seien Sie einfach froh, dass Sie nicht an NTFS hängen bleiben, was für viele Dateien in einem Verzeichnis wirklich miserabel ist. Ich würde JFS als Ersatz empfehlen, wenn Sie nicht Lust haben, den relativ neuen (aber anscheinend stabilen) ext4 FS zu verwenden.
quelle
Ist das Profilbild klein? Was ist mit dem Einfügen in die Datenbank mit den restlichen Profildaten? Dies ist möglicherweise nicht die beste Option für Sie, aber eine Überlegung wert ...
Hier ist ein (älteres) Microsoft-Whitepaper zum Thema: Zu BLOB oder nicht zu BLOB .
quelle
Ich habe eine kleine Webgalerie zusammen gehackt, in der ich eine Variation dieses Problems gefunden habe. Ich hatte "nur" ~ 30.000 Bilder im Cache-Verzeichnis, was sich als ziemlich langsam herausstellte (ext2 verwendet verknüpfte Listen für Verzeichnisindizes, wie ich mich erinnere).
Am Ende habe ich etwas in diese Richtung getan:
Dadurch werden die Daten in 256 Verzeichnisse aufgeteilt, wodurch eine schnelle Verzeichnissuche für jede der drei Ebenen möglich ist.
quelle
Das OpenBSD-verknüpfte Projekt "Epitome" ist keine sofortige Antwort auf Ihr Problem, aber Sie sollten darauf achten , dass Sie später darauf zurückgreifen können.
Epitome ist eine Engine, die Single Instance Storage-, Content Addressable Storage- und Deduplizierungsdienste bereitstellt.
Alle Ihre Daten werden in einem Datenspeicher als Hash-Blöcke gespeichert, wodurch nicht eindeutige Blöcke entfernt werden, um die Speicherplatznutzung zu verringern, und Sie können den Speichermechanismus im Wesentlichen vergessen, da Sie den Inhalt einfach per UUID aus dem Datenspeicher anfordern können.
Epitome ist derzeit experimentell, aber etwas, das Sie für die Zukunft beachten sollten.
quelle
Im Allgemeinen möchten Sie vermeiden, Verzeichnisse mit einer großen Anzahl von Dateien / Verzeichnissen zu haben. Der Hauptgrund ist, dass die Platzhaltererweiterung in der Befehlszeile zu "Zu vielen Argumenten" -Fehlern führt, die beim Versuch, mit diesen Verzeichnissen zu arbeiten, zu großen Schmerzen führen.
Suchen Sie nach einer Lösung, die einen tieferen, aber schmaleren Baum ergibt, z. B. indem Sie Unterordner erstellen, wie andere beschrieben haben.
quelle
Wir hatten ein ähnliches Problem. Die Lösung besteht - wie bereits erwähnt - darin, eine Hierarchie von Verzeichnissen zu erstellen.
Wenn Sie eine komplexe Anwendung haben, die auf einer flachen Verzeichnisstruktur basiert, müssen Sie wahrscheinlich viel patchen. Es ist also gut zu wissen, dass es eine Problemumgehung gibt. Verwenden Sie Symlinks, die nicht das erwähnte 32k-Limit haben. Dann haben Sie genügend Zeit, um die App zu reparieren ...
quelle
Warum nicht einen Zeitstempel-Ansatz verwenden und dann eine Überlaufoption haben?
Zum Beispiel
Angenommen, Ihr Zeitstempel lautet: 1366587600
Lassen Sie die letzten 2 Ziffern weg (sonst wird es einfach etwas lächerlich). Teilen Sie den Stempel in 4er-Sets auf (die Verzeichnisanzahl sollte nicht mehr als 9999 erreichen - wenn Sie möchten, können Sie ihn auch anders trennen).
Dies sollte Ihnen so etwas hinterlassen:
Überprüfen Sie dann auch den Betrag innerhalb des Verzeichnisses vor dem Hochladen. Wenn eine große Anzahl von Uploads erfolgt (z. B. 32000 + pro 100 Sekunden), wiederholen Sie das Verzeichnis in Sekunden oder Buchstaben, z. B.:
oder
Protokollieren Sie dann den Zeitstempel + Buchstaben oder den vollständigen Pfadcode zusammen mit dem Benutzer in einer Datenbank, und Sie sollten eingestellt sein.
Pfadstempel: 1366587600 oder 13665876a (wenn Sie Buchstaben verwenden).
Dies führt zwar zu einer großen Anzahl von Verzeichnissen, kann jedoch für die Bearbeitung von Dateirevisionen sehr nützlich sein. Wenn ein Benutzer beispielsweise ein neues Profilbild verwenden möchte, haben Sie immer noch die alte zeitgestempelte Version der älteren Version, falls er die Änderungen rückgängig machen möchte (nicht nur überschrieben).
quelle
Ich würde vorschlagen, zu entscheiden, wie viele maximale Unterverzeichnisse Sie im übergeordneten Ordner haben möchten (oder können).
Dann müssen Sie Ihre Benutzer-ID konvertieren, damit sie bei 1 beginnt.
Dann können Sie tun:
modulo = currentId % numberOfSubdirectories
modulo
enthält jetzt Ihre Unterverzeichnisnummer, die niemals größer sein wird, alsnumberOfSubdirectories
Sie ausgewählt haben.Machen Sie mit Modulo, was Sie wollen, zum Beispiel Hash.
Auch auf diese Weise werden Unterverzeichnisse linear gefüllt.
quelle