[Big Data] Componentes do MapReduce: partição e classificação

O problema leva a

É necessário enviar os resultados estatísticos para arquivos diferentes (partições) de acordo com as condições. Por exemplo: enviar os resultados estatísticos para diferentes arquivos (partições) de acordo com as diferentes províncias onde o telefone celular pertence

Semelhante a calouros <k, v> que entram na escola, diferentes alunos são alocados em dormitórios e, em seguida, entram em dormitórios diferentes (reduzir tarefas). Se a quantidade de dados enviada pelo mapa for muito grande, significa que todos esses dados irão para o nó de redução padrão. A execução não tem o objetivo de reduzir a computação paralela e a pressão de E / S também é grande. Este é o motivo da partição.

A partição padrão é obtida modulando o número de Reduce Tasks com base no hashCode da chave. O usuário não pode controlar qual chave é armazenada em qual partição.

public class HashPartitioner <K,V> extends Partitioner <K,V> {
     public int getPartition (Kkey,Vvalue, int numReduceTasks) {
         return (key.hashCode () & Integer. MAX_VALUE }}
    

a) Atribuir uma zona por padrão

b) Atribuir várias áreas corresponde a várias tarefas de redução, e cada tarefa irá compartilhar o código em reduzir quando for executada

c) Para partições personalizadas, o número de partições retornadas deve ser o mesmo que a tarefa de redução definida, especificamente: a classe de partição personalizada estende HashPartitioner, ao reescrever getPartition, o número de ramos retornados deve ser o mesmo que job.setNumReduceTasks (X) ; O número de X é o mesmo.

d) As partições personalizadas precisam contar com o particionador personalizado, o princípio de funcionamento é mostrado na (figura). A partir da figura, deve haver uma redução para uma partição, e cada redução processa os resultados de diferentes partições e os envia para partes diferentes. -r - 0000X.

Caso:

Exportar os resultados estatísticos para diferentes arquivos (partições) de acordo com as diferentes províncias onde o telefone celular pertence

(1) Dados de entrada

(2) Formato de entrada

ID do número do celular rede ip URL tráfego upstream tráfego downstream código de status da rede

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 dados de saída esperado

Arquivos começando com 137

ID do número do celular rede ip URL tráfego upstream tráfego downstream código de status da rede

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

Arquivos começando com 138

ID do número do celular rede ip URL tráfego upstream tráfego downstream código de status da rede

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

Arquivos começando com 139

ID do número do celular rede ip URL tráfego upstream tráfego downstream código de status da rede

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

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

Ideia: o número do telefone celular é usado como a chave e o valor da linha é usado como o valor

(1) No Mapreduce, os pares de kv produzidos pelo mapa são agrupados de acordo com a mesma chave e, em seguida, distribuídos para diferentes reducetasks. A regra de distribuição padrão é: distribuir de acordo com o número de hashcode% reducetask da chave

(2) Se você deseja agrupar de acordo com nossas próprias necessidades, você precisa reescrever o particionador de componente de distribuição de dados (agrupamento)

(3) O FlowPartitioner que configura uma partição personalizada herda a classe abstrata: Partitione , e coloca a primeira redução no início do telefone móvel 136 para completar as estatísticas. O resultado da saída está na partição número 0, e o mesmo é colocado para 137, 138, 139 e outros resultados. Para o número de partição 1-4;

( 4 ) Comece a filtrar a saída de resultados pelo mappper por meio do método getPartition () e a saída em diferentes números de partição por meio da comparação definida em 2;

( 5 ) Processamento de dados de partição por meio de redução diferente e saída para parte diferente r-0000x;

( 6 ) Adicione uma classe de partição personalizada e número de tarefas no trabalho de classe de driver :

 job.setPartitionerClass(CustomPartitioner.class)

 job.setNumReduceTasks(5)

Adicione um 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;
        }
    }
}

Adicione configurações de partição em 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);
    }
}

A classificação só precisa implementar o método compareTo no FlowBean

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

 

 

 

Acho que você gosta

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