sql >> Base de Datos >  >> NoSQL >> HBase

El problema de los archivos pequeños

Los archivos pequeños son un gran problema en Hadoop o, al menos, lo son si se tiene en cuenta la cantidad de preguntas en la lista de usuarios sobre este tema. En esta publicación, analizaré el problema y examinaré algunas soluciones comunes.

Problemas con archivos pequeños y HDFS

Un archivo pequeño es uno que es significativamente más pequeño que el tamaño de bloque HDFS (predeterminado 64 MB). Si está almacenando archivos pequeños, probablemente tenga muchos (de lo contrario, no recurriría a Hadoop), y el problema es que HDFS no puede manejar muchos archivos.

Cada archivo, directorio y bloque en HDFS se representa como un objeto en la memoria del nodo de nombre, cada uno de los cuales ocupa 150 bytes, como regla general. Entonces, 10 millones de archivos, cada uno usando un bloque, usaría alrededor de 3 gigabytes de memoria. Ampliar mucho más allá de este nivel es un problema con el hardware actual. Ciertamente mil millones de archivos no es factible.

Además, HDFS no está preparado para acceder de manera eficiente a archivos pequeños:está diseñado principalmente para el acceso de transmisión de archivos grandes. La lectura de archivos pequeños normalmente provoca muchas búsquedas y muchos saltos de nodo de datos a nodo de datos para recuperar cada archivo pequeño, todo lo cual es un patrón de acceso a datos ineficiente.

Problemas con archivos pequeños y MapReduce

Las tareas de mapa generalmente procesan un bloque de entrada a la vez (usando el FileInputFormat predeterminado). ). Si el archivo es muy pequeño y hay muchos, entonces cada tarea de mapa procesa muy poca entrada y hay muchas más tareas de mapa, cada una de las cuales impone una sobrecarga adicional de contabilidad. Compare un archivo de 1 GB dividido en 16 bloques de 64 MB y 10 000 archivos de 100 KB aproximadamente. Los 10 000 archivos usan un mapa cada uno, y el tiempo de trabajo puede ser decenas o cientos de veces más lento que el equivalente con un solo archivo de entrada.

Hay un par de características para ayudar a aliviar la sobrecarga de contabilidad:reutilización de JVM de tareas para ejecutar múltiples tareas de mapa en una JVM, evitando así alguna sobrecarga de inicio de JVM (consulte mapred.job.reuse.jvm.num.tasks propiedad) y MultiFileInputSplit que puede ejecutar más de una división por mapa.

¿Por qué se producen archivos pequeños?

Hay al menos dos casos

  1. Los archivos son partes de un archivo lógico más grande. Dado que HDFS solo admitió anexos recientemente, un patrón muy común para guardar archivos ilimitados (por ejemplo, archivos de registro) es escribirlos en fragmentos en HDFS.
  2. Los archivos son inherentemente pequeños. Imagina un gran corpus de imágenes. Cada imagen es un archivo distinto y no existe una forma natural de combinarlas en un archivo más grande.

Estos dos casos requieren soluciones diferentes. Para el primer caso, donde el archivo se compone de registros, el problema se puede evitar llamando a sync() de HDFS método  de vez en cuando para escribir continuamente archivos grandes. Alternativamente, es posible escribir un programa para concatenar los archivos pequeños.

Para el segundo caso, se necesita algún tipo de contenedor para agrupar los archivos de alguna forma. Hadoop ofrece algunas opciones aquí.

Archivos HAR

Los archivos de Hadoop (archivos HAR) se introdujeron en HDFS en 0.18.0 para aliviar el problema de muchos archivos que ejercen presión sobre la memoria del nodo de nombre. Los archivos HAR funcionan construyendo un sistema de archivos en capas sobre HDFS. Un archivo HAR se crea usando el hadoop archive comando, que ejecuta un trabajo de MapReduce para empaquetar los archivos que se archivan en una pequeña cantidad de archivos HDFS. Para un cliente que usa el sistema de archivos HAR, nada ha cambiado:todos los archivos originales son visibles y accesibles (aunque usando un har:// dirección URL). Sin embargo, la cantidad de archivos en HDFS se ha reducido.

La lectura de archivos en un HAR no es más eficiente que la lectura de archivos en HDFS y, de hecho, puede ser más lenta, ya que cada acceso a un archivo HAR requiere dos lecturas de archivos de índice además de la lectura del archivo de datos (consulte el diagrama). Y aunque los archivos HAR se pueden usar como entrada para MapReduce, no existe una magia especial que permita que los mapas operen sobre todos los archivos en el co-residente HAR en un bloque HDFS. Debería ser posible crear un formato de entrada que pueda aprovechar la ubicación mejorada de los archivos en los HAR, pero aún no existe. Tenga en cuenta que MultiFileInputSplit, incluso con las mejoras en HADOOP-4565 para elegir archivos en una división que son locales del nodo, necesitará una búsqueda por archivo pequeño. Sería interesante ver el rendimiento de esto en comparación con un SequenceFile, por ejemplo. En la actualidad, los HAR probablemente se utilicen mejor únicamente con fines de archivo.

Archivos de secuencia

La respuesta habitual a las preguntas sobre "el problema de los archivos pequeños" es:utilice un SequenceFile. La idea aquí es que use el nombre del archivo como clave y el contenido del archivo como valor. Esto funciona muy bien en la práctica. Volviendo a los 10 000 archivos de 100 KB, puede escribir un programa para ponerlos en un solo SequenceFile, y luego puede procesarlos en forma de transmisión (directamente o usando MapReduce) operando en SequenceFile. También hay un par de bonificaciones. SequenceFiles se pueden dividir, por lo que MapReduce puede dividirlos en fragmentos y operar en cada fragmento de forma independiente. También admiten compresión, a diferencia de los HAR. La compresión de bloques es la mejor opción en la mayoría de los casos, ya que comprime bloques de varios registros (en lugar de por registro).

Puede ser lento convertir datos existentes en SequenceFiles. Sin embargo, es perfectamente posible crear una colección de SequenceFiles en paralelo. (Stuart Sierra ha escrito una publicación muy útil sobre cómo convertir un archivo tar en un SequenceFile; herramientas como esta son muy útiles y sería bueno ver más de ellas). En el futuro, es mejor diseñar su canalización de datos para escribir los datos en la fuente directamente en un SequenceFile, si es posible, en lugar de escribir en archivos pequeños como un paso intermedio.

A diferencia de los archivos HAR, no hay forma de enumerar todas las claves en un SequenceFile, a menos que se lea todo el archivo. (MapFiles, que son como SequenceFiles con claves ordenadas, mantienen un índice parcial, por lo que tampoco pueden enumerar todas sus claves; consulte el diagrama).

SequenceFile está bastante centrado en Java. TFile está diseñado para ser multiplataforma y reemplazar a SequenceFile, pero aún no está disponible.

HBase

Si está produciendo muchos archivos pequeños, entonces, dependiendo del patrón de acceso, un tipo diferente de almacenamiento podría ser más apropiado. HBase almacena datos en MapFiles (SequenceFiles indexados) y es una buena opción si necesita realizar análisis de transmisión de estilo MapReduce con la búsqueda aleatoria ocasional. Si la latencia es un problema, entonces hay muchas otras opciones:consulte la excelente encuesta de Richard Jones sobre las tiendas de valores clave.