[ビッグデータ] MapReduceコンポーネント:パーティション分割と並べ替え

問題は

条件に応じて、統計結果を異なるファイル(パーティション)に出力する必要があります。例:携帯電話が属するさまざまな州に応じて、統計結果をさまざまなファイル(パーティション)に出力します

新入生<k​​、v>が学校に入学するのと同様に、さまざまな学生に寮が割り当てられ、さまざまな寮に入る(タスクを減らす)。マップによって送信されるデータの量が多すぎる場合、これらのデータはすべて次の場所に送られます。デフォルトのreduceノード。実行は並列コンピューティングを減らす目的を果たしておらず、IOプレッシャーも大きいです。これがパーティションの理由です。

デフォルトのパーティションは、キーのhashCodeに基づいてReduceタスクの数を調整することによって取得されます。ユーザーは、どのキーをどのパーティションに保存するかを制御できません。

パブリッククラスHashPartitioner <KV>延びパーティショナ<KV> {
    公共のint getPartition(Kのキー、Vの値、 int型numReduceTasks){
        リターン(key.hashCode()と整数。 MAX_VALUE }}
    

a)デフォルトでゾーンを割り当てます

b)複数の領域を割り当てることは、いくつかのreduceタスクに対応し、各タスクは、実行時にreduceのコードを共有します。

c)カスタムパーティションの場合、返されるパーティションの数は、定義されたreduceタスクと同じである必要があります。具体的には、カスタムパーティションクラスはHashPartitionerを拡張し、getPartitionを書き換える場合、返されるブランチの数はjob.setNumReduceTasks(X)と同じである必要があります。 ; Xの数は同じです。

d)カスタムパーティションはカスタムパーティショナーPartitionerに依存する必要があります。動作原理は(図)に示すとおりです。図から、1つのパーティションにreduceが必要であり、各reduceは異なるパーティションの結果を処理して出力します。さまざまなパーツ-r--0000X。

場合:

携帯電話が属するさまざまな州に応じて、統計結果をさまざまなファイル(パーティション)にエクスポートします

(1)入力データ

(2)入力フォーマット

id mobile number network ipURLアップストリームトラフィックダウンストリームトラフィックネットワークステータスコード

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

2、13845644121、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. 期待される出力データ形式

137で始まるファイル

id mobile number network ipURLアップストリームトラフィックダウンストリームトラフィックネットワークステータスコード

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

138で始まるファイル

id mobile number network ipURLアップストリームトラフィックダウンストリームトラフィックネットワークステータスコード

2、13845644121、192.196.100.2、、264、0、200

139で始まるファイル

id mobile number network ipURLアップストリームトラフィックダウンストリームトラフィックネットワークステータスコード

3、13956435636、192.196.100.3、、132、1512、200

4、13966251146、192.168.100.1、、240、0、404

アイデア:携帯電話番号がキーとして使用され、行の値が値として使用されます

(1)Mapreduceでは、マップによって出力されたkvペアが同じキーに従ってグループ化され、異なるreduceタスクに分散されます。デフォルトの配布ルールは次のとおりです。キーのhashcode%reducetask番号に従って配布します。

(2)独自のニーズに応じてグループ化する場合は、データ分散(グループ化)コンポーネントPartitionerを書き直す必要があります。

(3)カスタムパーティションを設定するFlowPartitionerは、抽象クラスPartitioneを継承し、携帯電話136の先頭に最初のreduceを配置して統計を完成させます。出力結果はパーティション番号0にあり、同じです。 137、138、139およびその他の結果のために配置されます。パーティション番号1〜4に。

4 getPartition()メソッドを介してmappperによって出力された結果のフィルター処理を開始し、2で設定された比較を介して異なるパーティション番号で出力します。

5 異なるreduceを介してパーティションデータを処理し、異なるpart-r-0000xに出力します。

6 カスタムパーティションクラスとタスク数をドライバークラスジョブに追加します。

 job.setPartitionerClass(CustomPartitioner.class)

 job.setNumReduceTasks(5)

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

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);
    }
}

並べ替えには、FlowBeanにcompareToメソッドを実装するだけで済みます。

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

 

 

 

おすすめ

転載: blog.csdn.net/Qmilumilu/article/details/104676456