El primer programa MapReduce escrito a mano - wordcount

Citar:

    Ya ejecuté el primer recuento de palabras de ejemplo que viene con hadoop. Esta vez lo escribimos a mano nosotros mismos. Esto es equivalente al helloworld en el lenguaje de programación. En
primer lugar, entendamos qué parte de MapReduce queremos escribir. Sabemos que hadoop Para procesar un archivo, primero se divide el archivo a procesar en muchas partes, se procesa por separado y finalmente se agregan los resultados para
formar el resultado final del procesamiento (es decir, la idea de dividir y conquistar). Por ejemplo, vea qué parte de todo el proceso de MapReduce es el código que escribimos.

Ejemplo de proceso específico de MapReduce

En primer lugar, tenemos un archivo de este tipo, el contenido del archivo es el siguiente:
hola mundo hola java
hola hadoop
es muy simple, un archivo tiene dos líneas. Entonces, ¿cómo hace hadoop las estadísticas de palabras? Vamos a describirlo con pasos:
Paso 1: Lea esto Archivo, divida las palabras en cada línea de este archivo por línea y luego forme una gran cantidad de resultados clave / valor. Después del procesamiento, es así
<hola, 1>
<mundo, 1>
<hola, 1>
<java, 1>
<hola, 1>
<hadoop, 1>
Paso 2: Clasificación Después de la
clasificación, el resultado
será <hadoop, 1>
<hola, 1>
<hola, 1>
<hola, 1>
<java, 1>
<mundo , 1>
Paso 3: Fusionar
El resultado de la fusión es el siguiente
<hadoop, 1>
<hola, 1,1,1>
<java, 1>
<mundo, 1>
Paso 4: Converge el resultado
<hadoop, 1>
<hola , 3>
<java, 1>
<mundo, 1>

Cuando se completa el cuarto paso, las estadísticas de palabras se completan realmente. Después de leer este ejemplo específico, debo tener una comprensión más clara del proceso de procesamiento de mapreduce.
Luego, debemos saber que el segundo y tercer paso son el marco hadoop Para ayudarnos a completar, donde realmente necesitamos escribir código es el primer y cuarto paso, el
primer paso corresponde al proceso de Mapa, y el cuarto paso corresponde al proceso de Reducir.

Escribir código mapreduce

Ahora lo que tenemos que hacer es completar el primer y cuarto paso del código
1. Crear un proyecto


Cree un proyecto java ordinario y luego haga clic en Siguiente hasta el final y elija el nombre del proyecto usted mismo.
2. Importe el hadoop usado en ese momento El paquete, estoy usando la versión hadoop-3.2.0 aquí, ¿qué paquetes deben importarse? Los paquetes
que se van a importar:
(1) Los paquetes en share / hadoop / common en el directorio hadoop (excepto el paquete de prueba, el (Ejemplo de prueba, no es necesario introducir)
(2). El paquete en común en la misma biblioteca que el anterior
(3) . El paquete en share / hadoop / mapreduce en el directorio hadoop
(4). La misma biblioteca en mapreduce que la anterior
Luego, el paquete se introduce estos paquetes en la idea, haga clic en Archivo-> Estructura del proyecto-> Módulos,
haga clic en el pequeño signo más a la derecha del introducido, solo dijo que el paquete jar

3. Una vez completada la introducción del paquete, creamos un archivo java llamado WordCount, y luego comenzamos a escribir el código.
Aquí para pegar el código directamente, __ preste atención a la parte de importación, ¿es igual que yo? __ Porque hay muchas clases con el mismo nombre, Viene de diferentes frascos, es fácil cometer errores.

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.util.StringTokenizer;

/**
 * @author wxwwt
 * @since 2019-09-15
 */
public class WordCount {

    /**
     * Object      : 输入文件的内容
     * Text        : 输入的每一行的数据
     * Text        : 输出的key的类型
     * IntWritable : 输出value的类型
     */
    private static class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {
        @Override
        protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            StringTokenizer itr = new StringTokenizer(value.toString());
            while (itr.hasMoreTokens()) {
                context.write(new Text(itr.nextToken()), new IntWritable(1));
            }
        }
    }

    /**
     * Text         :  Mapper输入的key
     * IntWritable  :  Mapper输入的value
     * Text         :  Reducer输出的key
     * IntWritable  :  Reducer输出的value
     */
    private static class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
        @Override
        protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            int count = 0;
            for (IntWritable item : values) {
                count += item.get();
            }
            context.write(key, new IntWritable(count));
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        // 创建配置
        Configuration configuration = new Configuration();
        // 设置hadoop的作业  jobName是WordCount
        Job job = Job.getInstance(configuration, "WordCount");
        // 设置jar
        job.setJarByClass(WordCount.class);
        // 设置Mapper的class
        job.setMapperClass(WordCountMapper.class);
        // 设置Reducer的class
        job.setReducerClass(WordCountReducer.class);
        // 设置输出的key和value类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        // 设置输入输出路径
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        // 待job执行完  程序退出
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }

}

Programa Mapper:

/**
 * Object      : 输入文件的内容
 * Text        : 输入的每一行的数据
 * Text        : 输出的key的类型
 * IntWritable : 输出value的类型
 */
private static class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {
    @Override
    protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
        StringTokenizer itr = new StringTokenizer(value.toString());
        while (itr.hasMoreTokens()) {
            context.write(new Text(itr.nextToken()), new IntWritable(1));
        }
    }
}

El contexto es el contexto global. Primero, StringTokenizer se usa para dividir el valor (es decir, los datos de cada línea) en muchas partes según los espacios. Si StringTokenizer no pasa el separador especificado, el valor predeterminado será
"\ t \ n \ r \ f "símbolo de nueva línea de la pestaña de espacio como delimitador, y luego use nextToken () para atravesar una cadena de espacios separados según .context.write (new Text (itr.nextToken () ), new IntWritable (1));
the Significa escribir la clave / valor en el contexto.
Nota: En la programación de Hadoop, String es Text y Integer es IntWritable. Esta es una clase encapsulada por Hadoop mismo.
Solo recuerde, es casi lo mismo que la clase original. Ingrese la palabra cuya clave es Texto, y el valor es 1 (cantidad estadística) de Escritura.

Reducir programa:

/**
 * Text         :  Mapper输入的key
 * IntWritable  :  Mapper输入的value
 * Text         :  Reducer输出的key
 * IntWritable  :  Reducer输出的value
 */
private static class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count = 0;
        for (IntWritable item : values) {
            count += item.get();
        }
        context.write(key, new IntWritable(count));
    }
}

Reducir termina el cuarto paso. Observamos el proceso de ejemplo anterior y sabemos que los parámetros de entrada en este momento son probablemente así
<hola, 1,1,1>,
por lo que habrá un proceso de atravesar los valores, que es Los tres se suman.

Entrada de programa:

public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
    // 创建配置
    Configuration configuration = new Configuration();
    // 设置hadoop的作业  jobName是WordCount
    Job job = Job.getInstance(configuration, "WordCount");
    // 设置jar
    job.setJarByClass(WordCount.class);
    // 设置Mapper的class
    job.setMapperClass(WordCountMapper.class);
    // 设置Reducer的class
    job.setReducerClass(WordCountReducer.class);
    // 设置输出的key和value类型
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);

    // 设置输入输出路径
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    // 待job执行完  程序退出
    System.exit(job.waitForCompletion(true) ? 0 : 1);
}

La entrada del programa aquí es más clara al mirar los comentarios. Se trata de establecer algunos parámetros y rutas requeridas por mapreduce, solo
escríbalo en consecuencia. Aquí hay un poco de atención

FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));

Cuando revisamos el primer programa de Hadoop antes de ejecutarlo, el comando probablemente sea
hadoop jar WordCount.jar / input / wordcount / file1 / output / wcoutput
Los dos parámetros detrás son la ruta de entrada y la ruta de salida del archivo, si nuestro código es modificado Si la posición del parámetro o la operación con otros parámetros, es
necesario corresponder a la posición del subíndice args.

4. Especifique el punto de entrada para que se ejecute el paquete jar.
Después de completar el código, podemos empaquetarlo.
Primero seleccione Archivo -> Estructura del proyecto -> Artefactos -> + -> JAR -> Desde módulos con dependencias,

luego seleccione el principal de WordCount justo ahora

y haga clic en Construir -> Construir A continuación, Artifacts

mostrará un cuadro para seleccionar Build y

luego generar un directorio de salida en el proyecto, encontrar el WordCount.jar que necesitamos en él y subirlo al servidor donde se encuentra Hadoop.
Esto es básicamente el final, porque los siguientes pasos y Al igual que en mi artículo anterior, puede consultar: hadoop ejecutar el recuento de palabras de la primera instancia

Precauciones:

Es posible ejecutar directamente

  hadoop jar WordCount.jar /input/wordcount/file1  /output/wcoutput

Fallará e informará una excepción:

Exception in thread "main" java.io.IOException: Mkdirs failed to create /XXX/XXX
  at org.apache.hadoop.util.RunJar.ensureDirectory(RunJar.java:106)
  at org.apache.hadoop.util.RunJar.main(RunJar.java:150)

Similar al anterior.

En este momento, debe eliminar la carpeta de licencia y el contenido del paquete jar. Puede consultar este enlace: stackoverflow
Ver los archivos y carpetas de la licencia en
jar jar tvf XXX.jar | grep -i licencia
y eliminar META-INF / El contenido de LICENCIA
zip -d XXX.jar META-INF / LICENSE

para resumir:

1. Comprender los pasos de operación de mapReduce, de modo que sepamos que solo necesitamos escribir el proceso de map y reduce. El paso intermedio ha sido procesado por el marco hadoop. En el futuro, otros programas también pueden referirse a este paso para escribir
2. La cadena en hadoop es Text, Integer es IntWritable. Recuerde, si lo usa incorrectamente, informará una excepción.
3. Cuando informe que Mkdirs no pudo crear / XXX / XXX, verifique si hay un problema con la ruta. De lo contrario, elimine el META-INF / en el paquete jar. LICENCIA

Materiales de referencia:

1.https: //hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html
2.https: //stackoverflow.com/questions/10522835/hadoop-java -io-ioexception-mkdirs-falló-al-crear-alguna-ruta

Supongo que te gusta

Origin blog.csdn.net/sc9018181134/article/details/100865699
Recomendado
Clasificación