sql >> Base de Datos >  >> RDS >> Mysql

Almacenamiento eficiente de imágenes cargadas por el usuario en el sistema de archivos

Tenemos un sistema de este tipo en gran producción con más de 30 000 archivos y más de 20 GB hasta la fecha...

   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")

Los archivos simplemente se almacenan en un único directorio con el número entero File_ID como nombre del archivo. Somos más de 30.000 sin problemas. He probado más alto sin problemas.

Esto usa RHEL 5 x86_64 con ext3 como sistema de archivos.

¿Lo haría de esta manera otra vez? No. Déjame compartir un par de ideas sobre un rediseño.

  1. La base de datos sigue siendo la "fuente principal" de información sobre los archivos.

  2. Cada archivo tiene un hash sha1() y se almacena en una jerarquía de sistema de archivos basada en ese hash:/FileData/ab/cd/abcd4548293827394723984723432987.jpg

  3. la base de datos es un poco más inteligente a la hora de almacenar metainformación en cada archivo. Sería un sistema de tres mesas:

    File :almacena información como nombre, fecha, IP, propietario y un puntero a un Blob (sha1)
    File_Meta :almacena pares clave/valor en el archivo, según el tipo de archivo. Esto puede incluir información como Image_Width, etc...
    Blob :almacena una referencia al sha1 junto con su tamaño.

Este sistema eliminaría los duplicados del contenido del archivo almacenando los datos a los que hace referencia un hash (varios archivos podrían hacer referencia a los mismos datos de archivo). Sería muy fácil hacer una copia de seguridad sincronizada de la base de datos de archivos usando rsync.

Además, se eliminarían las limitaciones de un directorio dado que contiene muchos archivos.

La extensión del archivo se almacenaría como parte del hash de archivo único. Por ejemplo, si el hash de un archivo vacío fuera abcd8765 ... Un .txt vacío archivo y vacío .php archivo se referiría al mismo hash. Más bien, deberían hacer referencia a abcd8765.php y abcd8765.txt . ¿Por qué?

Apache, etc. se puede configurar para elegir automáticamente el tipo de contenido y las reglas de almacenamiento en caché en función de la extensión del archivo. Es importante almacenar los archivos con un nombre válido y la extensión que refleje el contenido del archivo.

Verá, este sistema realmente podría aumentar el rendimiento al delegar la entrega de archivos a través de nginx. Consulte http://wiki.nginx.org/XSendfile .

Espero que esto ayude de alguna manera. Cuídate.