2011-01-02 10 views
9

Probablemente participe en un proyecto en el que un componente importante es el almacenamiento de una gran cantidad de archivos (en este caso imágenes, pero solo debe funcionar como almacenamiento de archivos).Almacenamiento de imágenes a gran escala

Se espera que la cantidad de archivos entrantes sea de alrededor de 500,000 por semana (con un promedio de alrededor de 100 Kb cada uno), alcanzando un máximo de 100,000 archivos por día y 5 por segundo. Se espera que el número total de archivos llegue a decenas de millones antes de alcanzar un equilibrio en el que los archivos expiran por varias razones a la velocidad de entrada.

Necesito un sistema que pueda almacenar alrededor de 5 archivos por segundo en horas pico, mientras lee alrededor de 4 y elimina 4 en cualquier momento.

Mi idea inicial es que un sistema de archivos NTFS simple con un servicio simple para almacenar, caducar y leer en realidad debería ser suficiente. Me imagino que el servicio creará subcarpetas para cada año, mes, día y hora para mantener el número de archivos por carpeta al mínimo y para permitir la caducidad manual en caso de que sea necesario.

Se ha discutido una gran solución NTFS here, pero aún podría seguir algunos consejos sobre qué problemas esperar al construir un almacenamiento con las especificaciones mencionadas, qué problemas de mantenimiento esperar y qué alternativas existen. Preferentemente, me gustaría evitar un almacenamiento distribuido, si es posible y práctico.

edición

Gracias por todos los comentarios y sugerencias. Algunos más información de bonificación sobre el proyecto:

Esta no es una aplicación web donde las imágenes son suministradas por los usuarios finales. Sin revelar demasiado, ya que está en la fase de contrato, está más en la categoría de control de calidad. Piensa en la planta de producción con cinta transportadora y sensores. No es un control de calidad tradicional, ya que el valor del producto depende completamente de que la base de datos de imágenes y metadatos funcione sin problemas.

Las imágenes son accedidas en un 99% por una aplicación autónoma en orden primero en entrar, primero en salir, pero también se producirá el acceso aleatorio de una aplicación de usuario. Las imágenes anteriores a un día servirán principalmente para fines de archivo, aunque ese propósito también es muy importante.

La caducidad de las imágenes sigue reglas complejas por varias razones, pero en algún momento se deben eliminar todas las imágenes. Las reglas de eliminación siguen la lógica empresarial en función de los metadatos y las interacciones del usuario.

Habrá tiempo de inactividad cada día, donde se puede realizar el mantenimiento.

Preferiblemente, el almacenamiento de archivos no tendrá que volver a comunicar la ubicación de la imagen al servidor de metadatos. La ubicación de la imagen debe deducirse de manera única de los metadatos, posiblemente a través de una base de datos de mapas, si se elige algún tipo de sistema hash o distribuido.

Así que mis preguntas son:

  • Qué tecnologías va a hacer un trabajo robusto?
  • ¿Qué tecnologías tendrán los costos de implementación más bajos?
  • ¿Qué tecnologías será más fácil de mantener por el departamento de TI del cliente?
  • ¿Qué riesgos existen para una tecnología dada a esta escala (5-20 TB de datos, 10-100 millones de archivos)?
+0

Tenga en cuenta los límites de directorio de archivos de #, nos encontramos con un problema en Redhat con un límite máximo de archivos por dir, fyi. – Jakub

+0

Es por eso que quería dividir los archivos en carpetas según su año, mes, día y hora. Después de todo, no espero más de 18000 archivos por hora. – Holstebroe

+0

También vea http://stackoverflow.com/questions/2104720/memory-leak-using-sql-filestream/2104944#2104944 –

Respuesta

4

Aquí hay algunos pensamientos al azar sobre la implementación y posibles problemas basados ​​en las siguientes suposiciones: tamaño de imagen promedio de 100 kb, y un estado estable de 50M (5GB) de imágenes. Esto también supone que los usuarios no tendrán acceso al almacén de archivos directamente, y lo hará a través de software o un sitio web:

  1. Medio de almacenamiento: El tamaño de las imágenes le dan equivale a un lugar ínfimo leer y escribir velocidades, Creo que los discos duros más comunes no tendrían un problema con este rendimiento. Sin embargo, los pondría en una configuración RAID1 para la seguridad de los datos. Las copias de seguridad no parecen ser un problema, ya que solo son 5 gb de datos.

  2. Almacenamiento de archivos: Para evitar problemas con los archivos máximos en un directorio, tomaría el hash (mínimo MD5, esta sería la más rápida, pero la más probable es la colisión. Y antes de que la gente diga que MD5 está roto, esto es para la identificación, y no para la seguridad. Un atacante podría rellenar imágenes para un segundo ataque de preimagen y reemplazar todas las imágenes con cabras, pero lo consideraremos improbable) y convertir eso a una cadena hexadecimal. Luego, cuando llega el momento de ocultar el archivo en el sistema de archivos, tome la cadena hexadecimal en bloques de 2 caracteres y cree una estructura de directorio para ese archivo en función de eso. P.ej. si el archivo se copia a abcdef, el directorio raíz sería ab y luego debajo de ese un directorio llamado cd, debajo del cual se almacenaría la imagen con el nombre abcdef. El nombre real se mantendrá en otro lugar (se trata más abajo).

    Con este enfoque, si comienza a alcanzar los límites del sistema de archivos (o problemas de rendimiento) de demasiados archivos en un directorio, puede simplemente hacer que la parte de almacenamiento de archivos cree otro nivel de directorios. También podría almacenar con los metadatos con cuántos niveles de directorios se creó el archivo, de modo que si se expande más adelante, no se buscarán los archivos más antiguos en los directorios más nuevos y más profundos.

    Otro beneficio aquí: si tiene problemas de velocidad de transferencia o problemas con el sistema de archivos en general, puede dividir fácilmente un conjunto de archivos en otras unidades. Simplemente cambie el software para mantener los directorios de nivel superior en diferentes unidades. Entonces, si quiere dividir la tienda por la mitad, 00-7F en una unidad, 80-FF en otra.

    Hashing también le permite el almacenamiento de instancia única, lo que puede ser agradable. Como los hashes de una población normal de archivos tienden a ser aleatorios, esto también debería generar una distribución uniforme de los archivos en todos los directorios.

  3. Almacenamiento de metadatos: Si bien las filas de 50M parecen mucho, la mayoría de los DBMS están diseñados para burlar esa cantidad de registros, con suficiente RAM, por supuesto. Lo siguiente está escrito en base a SQL Server, pero estoy seguro de que la mayoría de estos se aplicará a otros.Cree una tabla con el hash del archivo como la clave principal, junto con elementos como el tamaño, el formato y el nivel de anidación. A continuación, cree otra tabla con una clave artificial (una columna de Identidad interna estaría bien para esto), y también el nombre original del archivo (varchar (255) o lo que sea), y el hash como una clave externa de regreso a la primera tabla, y la fecha en que se agregó, con un índice en la columna del nombre del archivo. También agregue cualquier otra columna que necesite para averiguar si un archivo ha caducado o no. Esto le permitirá almacenar el nombre original si tiene personas tratando de poner el mismo archivo bajo diferentes nombres (pero son idénticos, ya que hash lo mismo).

  4. Mantenimiento: Esta debe ser una tarea programada. Deje que Windows se preocupe por cuándo se ejecuta su tarea, menos para que lo depure y se equivoque (¿qué pasa si realiza tareas de mantenimiento todas las noches a las 2:30 a.m. y está en algún lugar que observa el horario de verano/horario de verano 2:30 a.m. durante el cambio de primavera). Este servicio ejecutará una consulta en la base de datos para establecer qué archivos están caducados (en función de los datos almacenados por nombre de archivo, para que sepa cuándo caducan todas las referencias que apuntan a un archivo almacenado. Cualquier archivo hash que no esté referenciado por al menos una fila en la tabla de nombre de archivo ya no es necesaria). El servicio irá luego a eliminar estos archivos.

Creo que eso es todo por las partes principales.

EDIT: Mi comentario fue haciendo demasiado largo, se mueve en una edición:

¡Vaya, mi error, eso es lo que me pasa por hacer matemáticas cuando estoy cansado. En este caso, si desea evitar la redundancia adicional de agregar niveles de RAID (51 o 61, por ejemplo, reflejados en un conjunto rayado), el hashing generaría la ventaja de poder colocar 5 unidades de 1TB en el servidor, y luego tener el software de almacenamiento de archivos abarca las unidades mediante hash como se menciona al final de 2. Incluso podría RAID1 las unidades para mayor seguridad para esto.

La copia de seguridad sería más compleja, aunque los tiempos de creación/modificación del sistema de archivos aún serían válidos para hacer esto (podría hacer que toque cada archivo para actualizar su hora de modificación cuando se agrega una nueva referencia a ese archivo).

Veo un doble inconveniente de ir por fecha/hora para los directorios. En primer lugar, es poco probable que la distribución sea uniforme, esto hará que algunos directorios sean más completos que otros. Hashing se distribuiría de manera uniforme. En cuanto a la expansión, podría supervisar el espacio en la unidad mientras agrega archivos y comenzar a pasar a la siguiente unidad cuando se agote el espacio. Imagino que parte del vencimiento está relacionado con la fecha, por lo que las unidades anteriores comenzarían a vaciarse a medida que las nuevas se llenen, y tendrías que encontrar la forma de equilibrar eso.

El almacén de metadatos no tiene que estar en el servidor. Ya está almacenando datos relacionados con archivos en la base de datos. A diferencia de simplemente hacer referencia a la ruta directamente desde la fila donde se usa, haga referencia a la clave del nombre del archivo (la segunda tabla que mencioné) en su lugar.

Imagino que los usuarios usan algún tipo de web o aplicación para interactuar con la tienda, por lo que la inteligencia para averiguar dónde iría el archivo en el servidor de almacenamiento residiría allí, y simplemente compartiría las raíces de las unidades (o hacer algunas cosas elegantes con unión NTFS para poner todas las unidades en un subdirectorio). Si está esperando desplegar un archivo a través de un sitio web, cree una página en el sitio que tome el ID del nombre del archivo, luego realice la búsqueda en el DB para obtener el hash, luego dividiría el hash en cualquier configuración nivel, y solicite que sobre el recurso compartido al servidor, luego vuelva a transmitirlo al cliente. Si se espera que un UNC tenga acceso al archivo, haga que el servidor simplemente construya el UNC en su lugar.

Ambos métodos harían que la aplicación del usuario final dependa menos de la estructura en el propio sistema de archivos, y le facilitarán la tarea de modificar y ampliar su almacenamiento más adelante.

+0

Gracias por sus comentarios. 1. Sobre el tamaño, 50M * 100 Kb es 5TB, no 5GB. La copia de seguridad/restauración eficiente es una preocupación. 2. No creo que el uso de hash en los nombres de los archivos brinde ningún beneficio sobre mi sugerencia por qué las carpetas basadas en fecha/hora. Usar carpetas basadas en fecha/hora facilitaría la copia de seguridad/restauración de escenarios, por ejemplo, si desea restaurar los últimos archivos de 24 horas. – Holstebroe

+0

3. No habrá metadatos en el servidor de almacenamiento de archivos. Los archivos serán referidos desde tablas en otra base de datos que también determinarán qué archivos han expirado. Esto necesita ser un simple almacenamiento de archivos de alta capacidad independiente. – Holstebroe

+0

@Holstebroe, acabo de agregar algunos más detalles y sugerencias –

3

Almacene las imágenes en una serie de bases de datos SQLite. Suena loco al principio, pero en serio es más rápido que almacenarlos en el sistema de archivos directamente y ocupar menos espacio. SQLite es extremadamente eficiente almacenando datos binarios y almacenando los archivos en una base de datos agregada en lugar de archivos individuales del sistema operativo. Ahorra gastos generales cuando las imágenes no encajan en tamaños exactos de bloque (lo cual es significativo para muchos archivos). Además, los datos paginados en SQLite pueden proporcionarle un rendimiento más rápido en general de lo que obtendría con los archivos del sistema operativo.

SQLite tiene limitaciones de concurrencia en las escrituras, pero dentro de los límites de los que está hablando y puede mitigarse aún más mediante el uso inteligente de múltiples (cientos) bases de datos SQLite.

Pruébalo, estarás gratamente sorprendido.

+0

"(cientos) de bases de datos SQLite" - el mantenimiento suena como un dolor de cabeza –

+0

@Mitch Wheat, en comparación a millones de archivos? –

+0

@Samuel Neff: ¡sí, ahí está! –

1

Solo unas pocas sugerencias, basadas en la información general proporcionada aquí, sin conocer detalles sobre lo que su aplicación realmente hace o lo que hará.

  • uso SHA1 del archivo como un nombre de archivo (si es necesario, almacenamiento de usuario suministrado por el nombre del archivo en el DB)

    la cosa es que si se preocupan por los datos, se tendría que almacenar una suma de verificación de todos modos.
    Si usa sha1 (sha256, md5, otro hash), entonces será fácil validar los datos del archivo - lea el archivo , hash cacl, si coincide con el nombre, entonces los datos son válidos. Suponiendo que esto sea , una aplicación web de algún tipo, nombre de archivo basado en hash, se puede usar como etag al servir datos. (consulte su directorio .git para ver un ejemplo sobre esto). Esto supone que no se puede utilizar nombre del archivo suministrado por el usuario de todas formas, ya que el usuario puede enviar algo así como "<>? :(). Txt"

  • utilización estructura de directorios que tenga sentido desde el punto de vista de aplicación

    la prueba principal aquí es que debería ser posible identificar un archivo simplemente mirando en PATH \ FILE solo, sin hacer búsquedas de metadatos en DB. Si almacena/accede a patrones estrictamente basados ​​en el tiempo, entonces TIENE \ DATE \ HH \ FILE tendría sentido, si tiene archivos que son propiedad de los usuarios, entonces quizás STORE \ < 1st N dígitos de UID> \ UID \ FILE haría sentido.

  • transacciones de uso para operaciones de archivo/metadatos

    es decir, comienzan escritura de archivo TRX metadatos, intentar escribir un archivo de FS, en caso de éxito cometer TRX, de reversión en caso de error. Se debe tener el máximo cuidado para evitar una situación cuando tiene metadatos de archivo en DB y ningún archivo en FS y viceversa.

  • uso de varios lugares de almacenamiento de raíz

    decir STORE01 \ STORE02 \ Store \ - esto puede ayudar en el desarrollo (y más tarde con el horizontal). Es posible que varios desarrolladores utilicen una base de datos central y almacenamiento de archivos local en su máquina. Usar STORE desde el principio ayudará a evitar una situación cuando metadata/file comb. será válida en un caso de una aplicación, y no es válida en el otro ..

  • Nunca almacene pathes absolutos en el PP

Cuestiones relacionadas