Mapreduce serialización de Hadoop

bbf48a5f21c2b1999ba1bd00b528c9e6.jpeg

 

Tabla de contenido

 

¿Qué es la serialización?

Qué es la deserialización:

Por qué serializar:

Serialización en Java:

Serialización de Hadoop:

Interfaz de serialización personalizada:

Pasos para lograr la serialización:

Primero mire el código fuente para un análisis simple:

Práctica de casos de serialización:

Requisitos del caso:

(1) Datos de entrada:

(2) Formato de datos de entrada:

(3) Formato de datos de salida esperado

análisis de la demanda:

Escriba un programa MapperReduce:   


 

¿Qué es la serialización?

        La serialización es convertir objetos en la memoria en secuencias de bytes (u otros protocolos de transferencia de datos) para almacenamiento en disco (persistencia) y transmisión de red.

Qué es la deserialización:

        La deserialización consiste en convertir secuencias de bytes recibidas (u otros protocolos de transferencia de datos) o datos persistentes en el disco en objetos en la memoria.

Por qué serializar:

        En términos generales, los objetos "vivos" solo existen en la memoria y desaparecen cuando se apaga la alimentación. Y los objetos "en vivo" solo pueden ser utilizados por procesos locales y no pueden enviarse a otra computadora en la red. Sin embargo, la serialización puede almacenar objetos "vivos" y los objetos "vivos" se pueden enviar a computadoras remotas.

Serialización en Java:

        También hay serialización en Java, ¿por qué no usamos la serialización de Java a través de la idea?

Debido a que el marco de serialización de Java (Serializable) es un marco pesado con mucha información que lo acompaña (varia información de verificación, encabezado, sistema de herencia, etc.), no es conveniente para una transmisión eficiente en la red. Por lo tanto, Hadoop ha desarrollado un mecanismo de serialización (Writable) por sí mismo.

Serialización de Hadoop:

        La serialización de Hadoop es relativamente simplificada, con solo una verificación simple, compacta (uso eficiente del espacio de almacenamiento), rápida (gastos generales bajos para leer y escribir datos) e interoperable (compatible con la interacción en varios idiomas).

Interfaz de serialización personalizada:

        En el proceso de desarrollo, el tipo de serialización básico no puede cumplir con todos los requisitos. Por ejemplo, si un objeto bean se pasa dentro del marco de Hadoop (no es un tipo de datos básico (una clase determinada) ---- no hay un tipo de Hadoop correspondiente), entonces el objeto debe ser Implementar la interfaz de serialización.

Pasos para lograr la serialización:

Primero mire el código fuente para un análisis simple:

Interfaz de escritura (parece que no se puede analizar nada)

Dos métodos:

1.escribir: serializar

2.readFields: deserialización 

c315f0a572804ddca5aed2d73d226161.png

 (1) Al deserializar, es necesario llamar reflexivamente al constructor de parámetros nulos, por lo que debe haber un constructor de parámetros nulos

public FlowBean() {
	super();
}

(2) Anule los dos métodos en la interfaz *** (nota: el orden de deserialización es exactamente el mismo que el orden de serialización)

                Como la cola en la estructura de datos, primero en entrar, primero en salir, serializado primero, luego deserializado primero

(3) El método toString() debe reescribirse porque debe imprimirse; de ​​lo contrario, se imprimirá la dirección.

(4) Si necesita transmitir el bean personalizado en la clave, también debe implementar la interfaz Comparable, porque el proceso Shuffle en el cuadro MapReduce requiere que las claves se puedan ordenar. (Por ejemplo: en el blog anterior, las palabras que aparecen en último lugar en el cálculo de ocurrencias de palabras se ordenan en el orden de 26 letras en inglés)

Mire un código fuente de muestra (texto de cadena):

1bc7a6fd823244e7b13bb52b20f936c9.png

Vea la imagen de arriba para implementar la interfaz:

WritableComparable<BinaryComparable>

 Hacer un seguimiento:

0a319f3e22e440a8959684412f2e239b.png

 Vea que la interfaz hereda de la interfaz Comparable (que es una API en Java)

Práctica de casos de serialización:

Requisitos del caso:

        Cuente el tráfico ascendente total, el tráfico descendente total y el tráfico total consumido por cada número de teléfono móvil

(1) Datos de entrada:

1c5aa47d206d48b1a50e2bbaed4f8834.png

 

(2) Formato de datos de entrada:

7 13560436666 120.196.100.99 1116 954 200

id número de teléfono móvil red ip tráfico de enlace ascendente tráfico de enlace descendente código de estado de la red

(3) Formato de datos de salida esperado

13560436666 1116 954 2070

Número de teléfono móvil Tráfico de enlace ascendente Tráfico de enlace descendente total

análisis de la demanda:

        Ingrese los datos primero, después de ingresar los datos, debe ir a la etapa del mapeador --- "etapa de reducción ---" etapa de salida

etapa del mapeador:

Considere ingresar kv primero (k --- offset v es una fila de datos)

La salida (kv) es la entrada (kv) de la reducción (k utilizado en este ejemplo es el número de teléfono móvil, para contar el tráfico del número de teléfono móvil, v es el tráfico ascendente, el tráfico descendente y el total el tráfico necesita encapsular la clase de bean (objeto personalizado) Luego serializar la transmisión (¿por qué necesita serializarla? ----Porque el mapeador y reduce pueden no estar en el mismo servidor debido a problemas de recursos durante el proceso de recálculo))

La salida (kv) también es (número de teléfono móvil, clase de bean)

Escriba un programa MapperReduce:
   

1. Código FlowBean:

package com.tangxiaocong.mapreduce.writable;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

/*
*
* 定义bean类
* 需要实现writable
* 重写序列化和反序列化方法
* 重写空参构造
* 重写tostring方法
*
* */
public class FlowBean  implements Writable {
   private  long upFlow;
    private  long downFlow;
    private  long sumFlow;

    public long getUpFlow() {
        return upFlow;
    }

    public void setUpFlow(long upFlow) {
        this.upFlow = upFlow;
    }

    public long getDownFlow() {
        return downFlow;
    }

    public void setDownFlow(long downFlow) {
        this.downFlow = downFlow;
    }

    public long getSumFlow() {
        return sumFlow;
    }

    public void setSumFlow(long sumFlow) {
        this.sumFlow = sumFlow;
    }
    public void setSumFlow() {
        this.sumFlow = this.downFlow+this.upFlow;
    }
    //生成空参构造函数由于反射  快捷键alt   + insert

    public FlowBean() {
    }

    @Override
    public void write(DataOutput out) throws IOException {
        //序列化方法
        //  向缓冲流中写入Long类型的数据
        out.writeLong(upFlow);
        out.writeLong(downFlow);
        out.writeLong(sumFlow);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
//反序列化方法
        //读取缓冲区中数据
        this.upFlow= in.readLong();
        this.downFlow= in.readLong();
        this.sumFlow= in.readLong();
    }

    @Override
    public String toString() {
        return upFlow + "\t"+downFlow +"\t"+ sumFlow ;
    }
}

        2. Código del mapeador:

package com.tangxiaocong.mapreduce.writable;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class FlowMapper extends Mapper<LongWritable, Text,Text,FlowBean> {

    private Text outK=new Text();
    private  FlowBean outV=new FlowBean();  //调用的无参构造函数

    @Override
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, FlowBean>.Context context) throws IOException, InterruptedException {
        //1 获取一行
        //1	13736230513	192.196.100.1	www.atguigu.com	2481	24681	200

        String s = value.toString();// 将数据转换成string
        //2 进行切割

        String[] split = s.split("\t"); //将数据按写入形式进行切割
        //3 抓取想要的数据
        //根据角标获取  手机号  上行流量  下行流量


        String phone = split[1];
        String up = split[split.length - 3];//  不能正序 因为有的属性是没有字段的
        String down = split[split.length - 2];
//     封装输出的kv

        outK.set(phone);
        outV.setUpFlow(Long.parseLong(up));//  up为string类型
        outV.setDownFlow(Long.parseLong(down));
        outV.setSumFlow();          //

        //写出
        context.write(outK,outV);
    }
}

3. Reducir código:

package com.tangxiaocong.mapreduce.writable;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class FlowReducer extends Reducer  <Text,FlowBean,Text,FlowBean>{
   private FlowBean outv=new FlowBean();


    @Override
    protected void reduce(Text key, Iterable<FlowBean> values, Reducer<Text, FlowBean, Text, FlowBean>.Context context) throws IOException, InterruptedException {

         long totalUp=0;
         long totaldown=0;
         
        //分析   传入TEXT  为手机号  后边为集合(Bean类的对象的集合)输出还是一个一个bean类  (每个手机号的总和)
        for (FlowBean value : values) {  //传入的参数是同一个key的
            totalUp+=value.getUpFlow();
            totaldown+=value.getDownFlow();
        }
        //  现在求出的是每个手机号的总的上行流量  下行流量
            //封装  key不需要
        //outv
    outv.setUpFlow(totalUp);
    outv.setDownFlow(totaldown);
    outv.setSumFlow();
    //写出
        context.write(key,outv);
    }
}

4. Código del conductor:

package com.tangxiaocong.mapreduce.writable;

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

import java.io.IOException;

public class FlowDriver {
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        //获取JOB
        Configuration entries = new Configuration();
        Job job = Job.getInstance(entries);

        job.setJarByClass(FlowDriver.class);
        //关联mapper  和reduce
        job.setMapperClass(FlowMapper.class);
        job.setReducerClass(FlowReducer.class);

        //设置mapper  输出的key 和value
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(FlowBean.class);

        // 设置最终的数据输出的key和value 类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FlowBean.class);

        //设置数据的输入路径和输出路径
        FileInputFormat.setInputPaths(job, new Path("D:\\hadoop\\phone_data.txt"));
        FileOutputFormat.setOutputPath(job, new Path("D:\\hadoop\\output3"));
        //提交job
        boolean b = job.waitForCompletion(true);
        System.exit(b ? 0 : 1);

    }

}

 última carrera  

Hubo un error. Después de dos horas de depuración, la respuesta fue configurar la clase del mapeador en la clase del controlador para generar el tipo kv. Hubo un error y la coincidencia no fue exitosa. 

ahora funciona correctamente

a82371d2c82347b69dc78443de46502a.png

 2068443796d04721a34960b9e5f714c6.png

 41784ae70e2f44ee8b47682f7f208c25.png

 

 

 

Supongo que te gusta

Origin blog.csdn.net/m0_61469860/article/details/129650133
Recomendado
Clasificación