2011-08-22 59 views
12

Recientemente configuré la compresión LZO en Hadoop. ¿Cuál es la forma más fácil de comprimir un archivo en HDFS? Quiero comprimir un archivo y luego eliminar el original. ¿Debería crear un trabajo de MR con un IdentityMapper y un IdentityReducer que use compresión LZO?Hadoop: comprimir archivo en HDFS?

Respuesta

6

Le sugiero que escriba un trabajo de MapReduce que, como usted dice, solo usa el mapeador de identidad. Mientras lo hace, debería considerar escribir los datos en los archivos de secuencia para mejorar la carga del rendimiento. También puede almacenar archivos de secuencia en compresión de nivel de bloque y nivel de registro. Debería ver qué funciona mejor para usted, ya que ambos están optimizados para diferentes tipos de registros.

-3

Bueno, si comprime un solo archivo, puede ahorrar algo de espacio, pero no puede usar realmente la capacidad de Hadoop para procesar ese archivo, ya que la descompresión se debe realizar de forma secuencial en una sola tarea de Mapa. Si tiene muchos archivos, hay Hadoop Archive, pero no estoy seguro de que incluya algún tipo de compresión. El caso de uso principal para la compresión en el que puedo pensar es comprimir la salida de Maps que se enviará a Reduces (guardar en la E/S de red).

Oh, para responder a su pregunta más completa, probablemente necesite implementar su propio RecordReader y/o InputFormat para asegurarse de que todo el archivo sea leído por una sola tarea Map, y también utilizó el filtro de descompresión correcto.

+0

Hadoop tiene bibliotecas de compresión integradas, consulte http://www.cloudera.com/blog/2009/ 06/parallel-lzo-splittable-compression-for-hadoop /. – schmmd

+0

Interesante. Pensé que hablabas de que la entrada estaba comprimida, no comprimiendo la salida, lo siento. ¿Te importa la clasificación de los datos en el archivo de salida? Simplemente podría usar las API del sistema de archivos y ajustar el FSDataOutputStream en el filtro de compresión LZO si no le importa la clasificación del archivo de salida. Si lo hace, entonces FileOutputFormat.setCompressOutput() y setOutputCompressorClass(). Está justo en el Javadoc, lo encontré en 10 segundos a través de Google. – Drizzt321

19

Para mí, es menor sobrecarga escribir un trabajo Hadoop Streaming para comprimir archivos.

Este es el comando corro:

hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-streaming-0.20.2-cdh3u2.jar \ 
    -Dmapred.output.compress=true \ 
    -Dmapred.compress.map.output=true \ 
    -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \ 
    -Dmapred.reduce.tasks=0 \ 
    -input <input-path> \ 
    -output $OUTPUT \ 
    -mapper "cut -f 2" 

voy también suelen esconder el producto en una carpeta temporal en caso de que algo va mal:

OUTPUT=/tmp/hdfs-gzip-`basename $1`-$RANDOM 

Una nota adicional, no lo creo especifica un reductor en el trabajo de transmisión, pero ciertamente puedes. Obligará a ordenar todas las líneas, lo que puede llevar mucho tiempo con un archivo grande. Podría haber una forma de evitar esto anulando el particionador, pero no me molesté en descifrarlo. La parte desafortunada de esto es que posiblemente termines con muchos archivos pequeños que no utilizan bloques HDFS de manera eficiente. Esa es una razón para mirar Hadoop Archives

+0

¿por qué "cortar -f 2" en lugar de, por ejemplo, "gato"? – dranxo

+2

La entrada al asignador es una clave y un valor separados por una pestaña. La clave es el desplazamiento de bytes de la línea en el archivo y el valor es el texto de la línea. 'cut -f 2' muestra solo el valor. –

+0

¿Cómo puedo comprimir la carpeta en hdfs? – subhashlg26

3

El comando de transmisión de Jeff Wu junto con una concatenación de los archivos comprimidos dará un solo archivo comprimido. Cuando se transfiere un asignador que no es de Java al trabajo de transmisión y el formato de entrada es la transmisión de texto, solo se emite el valor y no la clave.

hadoop jar contrib/streaming/hadoop-streaming-1.0.3.jar \ 
      -Dmapred.reduce.tasks=0 \ 
      -Dmapred.output.compress=true \ 
      -Dmapred.compress.map.output=true \ 
      -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \ 
      -input filename \ 
      -output /filename \ 
      -mapper /bin/cat \ 
      -inputformat org.apache.hadoop.mapred.TextInputFormat \ 
      -outputformat org.apache.hadoop.mapred.TextOutputFormat 
hadoop fs -cat /path/part* | hadoop fs -put - /path/compressed.gz 
+0

Solo quiero asegurarme de que entiendo los comandos. El primero produce la salida en un archivo comprimido, pero el archivo real no está en formato * .gz, por lo que el segundo comando es cambiarle el nombre. – nevets1219

+0

No, el primer comando genera los archivos comprimidos * .gz ** parte ** (muchos de ellos). Y el segundo comando es para concatenar esos archivos de partes en un solo archivo 'compressed.gz'. – daemon12

+0

El comando anterior proporciona un carácter 'tab' adicional al final de cada línea de la salida comprimida – daemon12

3

Esto es lo que he usado:

/* 
* Pig script to compress a directory 
* input: hdfs input directory to compress 
*   hdfs output directory 
* 
* 
*/ 

set output.compression.enabled true; 
set output.compression.codec org.apache.hadoop.io.compress.BZip2Codec; 

--comma seperated list of hdfs directories to compress 
input0 = LOAD '$IN_DIR' USING PigStorage(); 

--single output directory 
STORE input0 INTO '$OUT_DIR' USING PigStorage(); 

aunque no es lzo lo que puede ser un poco más lento.

+0

¿Comprime cada archivo individual en el directorio de entrada, o la compresión trata a todos los archivos como un archivo grande y comprime eso, luego genera potencialmente muchos menos archivos? En el último caso, ¿hay alguna forma de especificar la cantidad de datos que cerdo debe intentar comprimir a la vez, p. 3Gb a la vez? – AatG

+0

Sí, cargará un directorio de entrada completo en un único alias y se generará como $ {OUT_DIR}/part-m - *. Bz2. Si quieres un directorio de entrada de 3Gb, entonces controla IN_DIR – dranxo

4

@Chitra que no puedo comentar debido a la edición reputación

Aquí está todo en un solo comando: En lugar de utilizar el segundo comando, se puede reducir en un archivo comprimido directamente

hadoop jar share/hadoop/tools/lib/hadoop-streaming-2.7.3.jar \ 
     -Dmapred.reduce.tasks=1 \ 
     -Dmapred.output.compress=true \ 
     -Dmapred.compress.map.output=true \ 
     -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.BZip2Codec \ 
     -input /input/raw_file \ 
     -output /archives/ \ 
     -mapper /bin/cat \ 
     -reducer /bin/cat \ 
     -inputformat org.apache.hadoop.mapred.TextInputFormat \ 
     -outputformat org.apache.hadoop.mapred.TextOutputFormat 

Por lo tanto, obtener una gran cantidad de espacio por tener sólo un archivo compresa

por ejemplo, digamos que tengo 4 archivos de 10 MB (que es texto sin formato, el formato JSON)

El mapa solo me da 4 archivos de 650 KB Si hago un mapa y lo reduzco Tengo 1 archivo de 1.05 MB

Cuestiones relacionadas