• Shuffle机制


    Map方法之后,Reduce方法之前的数据处理过程称之为Shuffle

     Partition分区

     默认分区是根据key的hashCode对ReduceTasks个数取模得到的。用户没法控制哪个key存在哪个分区

    自定义Partitioner步骤

    (1)自定义类继承Partitioner,重写getPartition()方法

     (2)在Job驱动中,设置自定义Partitioner

     (3)  自定义Partition后,要根据自定义Partitioner的逻辑设置相应数量的ReduceTask()

    4 分区总结

     (1) 如果ReduceTask   的数量>getPartiton的结果数,则会多产生几个空的输出文件part-r-000xx;

    (2)如果1

    (3)如果ReduceTask的数量=1,则不管MapTask端输出多少个分区文件,最终结果都会交给一个ReduceTask,最终也会只产生一个结果文件part-r-00000;

    (4)分区号必须从零开始,逐一累加

    Partition分区案例实操

    (1)需求

    将 统计结果按照手机归属地不同省份输出到不同文件中

    (1)输入数据

    phone_data

    (2)期望输出结果

    手机号136、137、138、139开头都分别放到一个独立的4个文件中,其他开头的放到一个文件中。

    (3)代码

    分区类

    1. package com.chenxiang.mapreduce.partioner2;
    2. import org.apache.hadoop.io.Text;
    3. import org.apache.hadoop.mapreduce.Partitioner;
    4. public class ProvincePartitioner extends Partitioner {
    5. @Override
    6. public int getPartition(Text text, FlowBean flowBean, int numPartitions) {
    7. //text手机号
    8. String phone = text.toString();
    9. String prePhone = phone.substring(0, 3);
    10. int partition;
    11. if ("136".equals(prePhone)) {
    12. partition = 0;
    13. } else if ("137".equals(prePhone)) {
    14. partition = 1;
    15. } else if ("138".equals(prePhone)) {
    16. partition = 2;
    17. } else if ("139".equals(prePhone)) {
    18. partition = 3;
    19. } else {
    20. partition = 4;
    21. }
    22. return partition;
    23. }
    24. }

    Map类

    1. package com.chenxiang.mapreduce.partioner2;
    2. import org.apache.hadoop.io.LongWritable;
    3. import org.apache.hadoop.io.Text;
    4. import org.apache.hadoop.mapreduce.Mapper;
    5. import java.io.IOException;
    6. public class FlowMapper extends Mapper {
    7. private Text outK = new Text();
    8. private FlowBean outV = new FlowBean();
    9. @Override
    10. protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    11. // //获取一行信息
    12. String line = value.toString();
    13. String[] split = line.split("\t");//切割
    14. // 抓取数据
    15. String phone = split[1];
    16. String up = split[split.length - 3];
    17. String down = split[split.length - 2];
    18. //封装
    19. outK.set(phone);
    20. outV.setUpFlow(Long.parseLong(up));
    21. outV.setDownFlow(Long.parseLong(down));
    22. outV.setSumFlow();
    23. // 写出
    24. context.write(outK,outV);
    25. }
    26. }

    Reducer类

    1. package com.chenxiang.mapreduce.partioner2;
    2. import org.apache.hadoop.io.Text;
    3. import org.apache.hadoop.mapreduce.Reducer;
    4. import java.io.IOException;
    5. public class FlowReducer extends Reducer {
    6. private FlowBean outV =new FlowBean();
    7. @Override
    8. protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
    9. //遍历累加值
    10. long totalUp=0;
    11. long totalDown=0;
    12. for(FlowBean value:values)
    13. {
    14. totalUp+=value.getUpFlow();
    15. totalDown+=value.getDownFlow();
    16. }
    17. //2 封装
    18. outV.setDownFlow(totalDown);
    19. outV.setUpFlow(totalUp);
    20. outV.setSumFlow();
    21. context.write(key,outV);
    22. }
    23. }

    Driver类

    1. package com.chenxiang.mapreduce.partioner2;
    2. import org.apache.hadoop.conf.Configuration;
    3. import org.apache.hadoop.fs.Path;
    4. import org.apache.hadoop.io.Text;
    5. import org.apache.hadoop.mapreduce.Job;
    6. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    7. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    8. import java.io.IOException;
    9. public class FlowDriver {
    10. public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
    11. // 1 获取job
    12. Configuration conf = new Configuration();
    13. Job job = Job.getInstance(conf);
    14. //2 设置jar
    15. job.setJarByClass(FlowDriver.class);
    16. //3 关联 mapper reducer
    17. job.setMapperClass(FlowMapper.class);
    18. job.setReducerClass(FlowReducer.class);
    19. // 4 设置Mapper输出类型
    20. job.setMapOutputValueClass(FlowBean.class);
    21. job.setMapOutputKeyClass(Text.class);
    22. job.setPartitionerClass(ProvincePartitioner.class);
    23. job.setNumReduceTasks(5);
    24. //设置Mapper最终输出路径
    25. job.setOutputValueClass(FlowBean.class);
    26. job.setOutputKeyClass(Text.class);
    27. //6 设置数据的输入路径和输出路径
    28. FileInputFormat.setInputPaths(job, new Path("D:\\input\\inputflow"));
    29. FileOutputFormat.setOutputPath(job, new Path("D:\\output\\output114514"));
    30. //7 提交job
    31. boolean result = job.waitForCompletion(true);
    32. System.exit(result ? 0 : 1);
    33. }
    34. }

    bean类

    1. package com.chenxiang.mapreduce.partioner2;
    2. import org.apache.hadoop.io.Writable;
    3. import java.io.DataInput;
    4. import java.io.DataOutput;
    5. import java.io.IOException;
    6. /*
    7. *
    8. * 1 定义类实现writable接口
    9. * 2 重写序列化和反序列化方法
    10. * 3 空参构造方法
    11. * 4 toString 方法*/
    12. public class FlowBean implements Writable {
    13. private long upFlow;//上行流量
    14. private long downFlow;//下行流量
    15. private long sumFlow;//总流量
    16. //空参构造
    17. public long getUpFlow() {
    18. return upFlow;
    19. }
    20. public void setUpFlow(long upFlow) {
    21. this.upFlow = upFlow;
    22. }
    23. public long getDownFlow() {
    24. return downFlow;
    25. }
    26. public void setDownFlow(long downFlow) {
    27. this.downFlow=downFlow;
    28. }
    29. public long getSumFlow() {
    30. return sumFlow;
    31. }
    32. public void setSumFlow() {
    33. this.sumFlow= this.upFlow+this.downFlow;
    34. }
    35. public FlowBean() {
    36. }
    37. @Override
    38. public void write(DataOutput out) throws IOException {
    39. out.writeLong(upFlow);
    40. out.writeLong(downFlow);
    41. out.writeLong(sumFlow);
    42. }
    43. @Override
    44. public void readFields(DataInput in) throws IOException {
    45. this.upFlow= in.readLong();
    46. this.downFlow=in.readLong();
    47. this.sumFlow=in.readLong();
    48. }
    49. @Override
    50. public String toString() {
    51. return upFlow+"\t"+downFlow+"\t"+sumFlow; }
    52. }

  • 相关阅读:
    阿里二面:JVM调优你会吗?
    react面试题总结一波,以备不时之需
    护眼灯国A与国AA级差别是什么?推荐双十一值得入手的国AA的护眼灯
    黑客帝国:随机字母生成器
    Centos7 安装Seata1.5.1
    C嘎嘎 - 内存分区
    Linux命令:free命令
    Windows客户端下pycharm配置跳板机连接内网服务器
    可道云:像Windows操作一样的企业网盘
    金属非金属如何去毛刺 机器人浮动去毛刺
  • 原文地址:https://blog.csdn.net/m0_65136138/article/details/126078548