[Big Data] Componentes de MapReduce: partición y clasificación

El problema conduce a

Es necesario enviar los resultados estadísticos a diferentes archivos (particiones) de acuerdo con las condiciones. Por ejemplo: envíe los resultados estadísticos a diferentes archivos (particiones) de acuerdo con las diferentes provincias a las que pertenece el teléfono móvil

De manera análoga a los estudiantes de primer año <k, v> que ingresan a la escuela, a diferentes estudiantes se les asignan dormitorios y luego ingresan a diferentes dormitorios (reducir tareas). Si la cantidad de datos enviados por el mapa es demasiado grande, significa que todos estos datos irán a el nodo de reducción predeterminado.La ejecución no tiene el propósito de reducir la computación paralela, y la presión de E / S también es grande. Ésta es la razón de la partición.

La partición predeterminada se obtiene modulando el número de Reducir tareas según el código hash de la clave. El usuario no puede controlar qué clave se almacena en qué partición.

public class HashPartitioner <K,V> extiende Partitioner <K,V> {
     public int getPartition (teclaK,valorV, int numReduceTasks) {
         return (key.hashCode () & Integer. MAX_VALUE }}
    

a) Asignar una zona por defecto

b) Asignar varias áreas corresponde a varias tareas de reducción, y cada tarea compartirá el código en reducción cuando se ejecute

c) Para particiones personalizadas, el número de particiones devueltas debe ser el mismo que el de la tarea de reducción definida, específicamente: la clase de partición personalizada extiende HashPartitioner, al reescribir getPartition, el número de ramas devueltas debe ser el mismo que job.setNumReduceTasks (X) ; El número de X es el mismo.

d) Las particiones personalizadas deben depender del particionador personalizado Partitioner, el principio de funcionamiento es el que se muestra en (imagen). De la figura, debe haber una reducción para una partición, y cada reducción procesa los resultados de diferentes particiones y los envía a diferentes partes -r - 0000X.

Caso:

Exportar los resultados estadísticos a diferentes archivos (particiones) según las diferentes provincias a las que pertenece el teléfono móvil

(1) Datos de entrada

(2) Formato de entrada

ID número de móvil IP de red URL tráfico ascendente tráfico descendente código de estado de la red

1, 13736230513, 192.196.100.1, www.atguigu.com,  2481, 24681, 200

2, 13846544121, 192.196.100.2 ,, 264, 0, 200

3, 13956435636, 192.196.100.3 ,, 132, 1512, 200

4, 13966251146, 192.168.100.1 ,, 240, 0, 404

  1. Formato de datos de salida esperado

Archivos que comienzan con 137

ID número de móvil IP de red URL tráfico ascendente tráfico descendente código de estado de la red

1, 13736230513, 192.196.100.1, www.atguigu.com,  2481, 24681, 200

Archivos que comienzan con 138

ID número de móvil IP de red URL tráfico ascendente tráfico descendente código de estado de la red

2, 13846544121, 192.196.100.2 ,, 264, 0, 200

Archivos que comienzan con 139

ID número de móvil IP de red URL tráfico ascendente tráfico descendente código de estado de la red

3, 13956435636, 192.196.100.3 ,, 132, 1512, 200

4, 13966251146, 192.168.100.1 ,, 240, 0, 404

Idea: el número de teléfono móvil se utiliza como clave y el valor de la fila se utiliza como valor

(1) En Mapreduce, los pares de kv generados por el mapa se agrupan de acuerdo con la misma clave y luego se distribuyen a diferentes tareas de reducción. La regla de distribución predeterminada es: distribuir de acuerdo con el código hash% reduce el número de tarea de la clave

(2) Si desea agrupar de acuerdo con nuestras propias necesidades, debe volver a escribir el componente de distribución de datos (agrupación) Particionador

(3) El FlowPartitioner que configura una partición personalizada hereda la clase abstracta: Partitione y coloca la primera reducción al comienzo del teléfono móvil 136 para completar las estadísticas. El resultado de salida está en la partición número 0, y el mismo es colocado para 137, 138, 139 y otros resultados.A la partición número 1-4;

( 4 ) Comience a filtrar la salida de resultados por mappper a través del método getPartition (), y la salida en diferentes números de partición a través del conjunto de comparación en 2;

( 5 ) Procesamiento de datos de partición a través de diferentes reducciones y salidas a diferentes part-r-0000x;

( 6 ) Agregue una clase de partición personalizada y un número de tareas en el trabajo de la clase del controlador :

 job.setPartitionerClass(CustomPartitioner.class)

 job.setNumReduceTasks(5)

Agregar un FlowPartitioner.class

package hdfs_demo.partiyioner;


import hdfs_demo.telFlow.FlowBean;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

public class FlowPartitioner extends Partitioner<Text, FlowBean> {
    /**
     * 返回分区号
     * @param text
     * @param flowBean
     * @param numPartitions
     * @return
     */
    //进行分区
    public int getPartition(Text text, FlowBean flowBean, int numPartitions) {

        String phone = text.toString();//获取手机号

        switch (phone.substring(0,3)){
            case "136":
                return 0;
            case "137":
                return 1;
            case "138":
                return 2;
            case "139":
                return 3;
            default:
                return 4;
        }
    }
}

Agregue la configuración de la partición en FlowDriver.class:

package hdfs_demo.partiyioner;

import hdfs_demo.telFlow.FlowBean;
import hdfs_demo.telFlow.FlowMapper;
import hdfs_demo.telFlow.FlowReducer;
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, ClassNotFoundException, InterruptedException {
        //创建配置对象
        Configuration conf = new Configuration();
        //创建一个job对象
        Job job = Job.getInstance(conf, "telFlowCount");

        //mapreduce的启动类
        job.setJarByClass(FlowDriver.class);

        //设置mapper 和reducer
        job.setMapperClass(FlowMapper.class);
        job.setReducerClass(FlowReducer.class);

        //设置map的输出类型  Text, FlowBean
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(FlowBean.class);

        //设置reduce的输出类型  Text, FlowBean
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FlowBean.class);

        // 在驱动类job中添加自定义分区类和任务数量
        job.setPartitionerClass(FlowPartitioner.class);
        job.setNumReduceTasks(5);

        //设置输入数据路径
        FileInputFormat.setInputPaths(job, new Path("G:\\idea-workspace\\hdfs_java_api\\Resource\\telinfo.txt"));
        //设置reducer输出结果的路径
        FileOutputFormat.setOutputPath(job, new Path("G:\\idea-workspace\\hdfs_java_api\\Resource\\result"));

        //提交任务
        boolean b = job.waitForCompletion(true);

        System.out.println(b);
    }
}

La clasificación solo necesita implementar el método compareTo en FlowBean

public int compareTo(Object o) {
        return 0;
    }
}
 public int compareTo(Object o) {
        FlowBean bean =(FlowBean )o;
        // 倒序排列,从大到小
        return this.sumFlow>bean.getSumFlow() ? -1 : 1;
    }

 

 

 

Supongo que te gusta

Origin blog.csdn.net/Qmilumilu/article/details/104676456
Recomendado
Clasificación