Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Effizientes Speichern von vom Benutzer hochgeladenen Bildern im Dateisystem

Wir haben ein solches System in starker Produktion mit über 30.000 Dateien und 20+ GB bis heute...

   Column    |            Type             |                        Modifiers                         
-------------+-----------------------------+----------------------------------------------------------
 File_ID     | integer                     | not null default nextval('"ACRM"."File_pseq"'::regclass)
 CreateDate  | timestamp(6) with time zone | not null default now()
 FileName    | character varying(255)      | not null default NULL::character varying
 ContentType | character varying(128)      | not null default NULL::character varying
 Size        | integer                     | not null
 Hash        | character varying(40)       | not null
Indexes:
    "File_pkey" PRIMARY KEY, btree ("File_ID")

Die Dateien werden nur in einem einzigen Verzeichnis mit der ganzzahligen File_ID als Dateinamen gespeichert. Wir sind über 30.000 ohne Probleme. Ich habe höhere Werte ohne Probleme getestet.

Dies verwendet RHEL 5 x86_64 mit ext3 als Dateisystem.

Würde ich es wieder so machen? Nein. Lassen Sie mich ein paar Gedanken zu einem Redesign teilen.

  1. Die Datenbank ist immer noch die "Hauptquelle" für Informationen zu den Dateien.

  2. Jede Datei wird sha1() gehasht und basierend auf diesem Hash in einer Dateisystemhierarchie gespeichert:/FileData/ab/cd/abcd4548293827394723984723432987.jpg

  3. Die Datenbank ist etwas klüger, wenn es darum geht, Metainformationen zu jeder Datei zu speichern. Es wäre ein Drei-Tabellen-System:

    File :speichert Informationen wie Name, Datum, IP, Besitzer und einen Zeiger auf ein Blob (sha1)
    File_Meta :speichert je nach Dateityp Schlüssel/Wert-Paare in der Datei. Dies kann Informationen wie Image_Width usw. enthalten...
    Blob :speichert einen Verweis auf sha1 zusammen mit seiner Größe.

Dieses System würde den Dateiinhalt deduplizieren, indem es die Daten speichert, auf die ein Hash verweist (mehrere Dateien könnten auf dieselben Dateidaten verweisen). Es wäre sehr einfach, die Dateidatenbank mit rsync zu synchronisieren.

Außerdem würden die Beschränkungen eines gegebenen Verzeichnisses, das viele Dateien enthält, eliminiert.

Die Dateierweiterung würde als Teil des eindeutigen Datei-Hash gespeichert. Zum Beispiel, wenn der Hash für eine leere Datei abcd8765 wäre ... Eine leere .txt Datei und leere .php Datei würde auf denselben Hash verweisen. Stattdessen sollten sie sich auf abcd8765.php beziehen und abcd8765.txt . Warum?

Apache usw. kann so konfiguriert werden, dass der Inhaltstyp und die Caching-Regeln basierend auf der Dateierweiterung automatisch ausgewählt werden. Es ist wichtig, die Dateien mit einem gültigen Namen und der Erweiterung zu speichern, die den Inhalt der Datei widerspiegelt.

Sie sehen, dieses System könnte die Leistung wirklich steigern, indem es die Dateilieferung über nginx delegiert. Siehe http://wiki.nginx.org/XSendfile .

Ich hoffe, das hilft irgendwie. Pass auf dich auf.