Hadoop: comprimir archivo en HDFS?

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?

Te sugiero que escribas un trabajo de MapReduce que, como dices, 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.

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

Este es el comando que 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  \ -output $OUTPUT \ -mapper "cut -f 2" 

También esconderé la salida en una carpeta temporal en caso de que algo salga mal.

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

Una nota adicional, no especifico 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 de las razones para mirar los archivos de Hadoop

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, puede ser un poco más lento.

@Chitra No puedo hacer ningún comentario debido a un problema de reputación

Aquí hay todo en un comando: en lugar de usar el segundo comando, 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, ganas mucho espacio teniendo solo un archivo comprimido

Por ejemplo, digamos que tengo 4 archivos de 10MB (es texto plano, 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.

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 

Sé que esto es un hilo viejo, pero si alguien sigue este hilo (como yo) sería útil saber que cualquiera de los siguientes 2 métodos te da un carácter de tab (\ t) al final de cada línea

  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  \ -output $OUTPUT \ -mapper "cut -f 2" 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 

A partir de esto, hadoop-streaming.jar agrega x’09 ‘al final de cada línea , encontré la corrección y necesitamos establecer los siguientes 2 parámetros para respetar el delimitador que usas (en mi caso fue)

  -Dstream.map.output.field.separator=, \ -Dmapred.textoutputformat.separator=, \ 

comando completo para ejecutar

 hadoop jar /jars/hadoop-streaming-2.6.0-cdh5.4.11.jar \ -Dmapred.reduce.tasks=1 \ -Dmapred.output.compress=true \ -Dmapred.compress.map.output=true \ -Dstream.map.output.field.separator=, \ -Dmapred.textoutputformat.separator=, \ -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.Lz4Codec \ -input file:////home/admin.kopparapu/accenture/File1_PII_Phone_part3.csv \ -output file:///home/admin.kopparapu/accenture/part3 \ -mapper /bin/cat \ -reducer /bin/cat \ -inputformat org.apache.hadoop.mapred.TextInputFormat \ -outputformat org.apache.hadoop.mapred.TextOutputFormat 

Bueno, si comprime un solo archivo, puede ahorrar algo de espacio, pero realmente no puede usar el poder de Hadoop para procesar ese archivo, ya que la descompresión se debe hacer en una sola tarea de mapa secuencialmente. Si tienes muchos archivos, está 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 haya sido leído por una sola tarea Map, y también haya utilizado el filtro de descompresión correcto.