Cómo almacenar imágenes en su sistema de archivos

Actualmente, tengo imágenes (máximo 6 MB) almacenadas como BLOB en una tabla InnoDB. A medida que aumenta el tamaño de los datos, la copia de seguridad nocturna crece cada vez más lentamente y obstaculiza el rendimiento normal.

Entonces, los datos binarios deben ir al sistema de archivos. (los punteros a los archivos se mantendrán en la base de datos).

Los datos tienen una relación tipo árbol:

- main site - user_0 - album_0 - album_1 - album_n - user_1 - user_n etc... 

Ahora quiero que los datos se distribuyan de manera uniforme a través de la estructura del directorio. ¿Cómo debo lograr esto?

Creo que podría probar MD5('userId, albumId, imageId'); y cortar la cadena resultante para obtener mi ruta de directorio:

   /var/imageStorage/f/347e/013b/c042/51cf/985f7ad0daa987d.jpeg

Esto me permitiría asignar el primer carácter a un servidor y distribuir uniformemente la estructura de directorios en múltiples servidores.

Sin embargo, esto no mantendría las imágenes organizadas por usuario, lo que probablemente propagaría las imágenes de 1 álbum en varios servidores.

Mi pregunta es:
¿Cuál es la mejor manera de almacenar los datos de imagen en el sistema de archivos de una manera equilibrada, mientras se mantienen los datos de usuario / álbum juntos?

¿Estoy pensando en la dirección correcta? o esta es la forma incorrecta de hacer las cosas del todo?

Actualizar:
Iré por el corte de cadena md5(user_id) para la división en el nivel más alto. Y luego ponga todos los datos de usuario en ese mismo cubo. Esto asegurará una distribución uniforme de los datos y al mismo tiempo mantendrá los datos del usuario almacenados juntos.

   / var
    - imageStorage
      - f / 347e / 013b
        - f347e013bc04251cf985f7ad0daa987d
          - 0
            - album1_10
              - picture_1.jpeg
          - 1
            - album1_1
              - picture_2.jpeg
              - picture_3.jpeg
            - album1_11
              - picture_n.jpeg
          - n
            - album1_n

Creo que utilizaré albumId dividido desde atrás (me gusta esa idea) para mantener el número de álbumes por directorio más pequeño (aunque no será necesario para la mayoría de los usuarios).

¡Gracias!

Simplemente divida su ID de usuario por detrás. p.ej

 UserID = 6435624 Path = /images/24/56/6435624 

En cuanto a la copia de seguridad, puede utilizar la replicación de MySQL y hacer una copia de seguridad de la base de datos esclava para evitar problemas (por ejemplo, lockings) durante la copia de seguridad.

Una cosa es distribuir los nombres de los archivos en diferentes directorios, si considera dividir sus nombres de archivos md5 en diferentes subdirectorios (lo cual es una buena idea), sugeriría mantener el hash completo como nombre de archivo y duplicar los primeros caracteres como nombres de directorio. De esta forma, facilitará la identificación de archivos, por ejemplo, cuando tiene que mover directorios.

p.ej

abcdefgh.jpg -> a / ab / abc / abcdefgh.jpg

si sus nombres de archivo no están distribuidos uniformemente (no es un hash), intente elegir un método de división que obtenga una distribución pareja, por ejemplo, los últimos caracteres si se trata de una ID de usuario en aumento

Estoy usando esta estrategia dado una identificación con foto única

  • invierta la cuerda
  • zerofill con cero delante si hay un número impar de dígitos
  • dividir la cadena en subcadenas de dos dígitos
  • construye el camino como abajo

     17 >> 71 >> /71.jpg 163 >> 0361 >> /03/61.jpg 6978 >> 8796 >> /87/96.jpg 1687941 >> 01497861 >> /01/49/78/61.jpg 

Este método garantiza que cada carpeta contenga hasta 100 imágenes y 100 subcarpetas y la carga se distribuye uniformemente entre las carpetas de la izquierda.

Además, solo necesita el ID de la imagen para llegar al archivo, no es necesario leer la tabla de imágenes que contiene otros metadatos. Los datos del usuario no se almacenan muy cerca y la relación ID-Path es predecible, depende de sus necesidades.