@

排序概述

  • 排序是MapReduce框架中最重要的操作之一。
  • Map Task和ReduceTask均会默认对数据按照key进行排序。该操作属于Hadoop的默认行为。任何应用程序中的数据均会被排序,而不管逻辑上是否需要。
  • 黑默认排序是按照字典顺序排序,且实现该排序的方法是快速排序。
  • 对于MapTask,它会将处理的结果暂时放到一个缓冲区中,当缓冲区使用率达到一定阈值后,再对缓冲区中的数据进行一次排序,并将这些有序数据写到磁盘上,而当数据处理完毕后,它会对磁盘上所有文件进行一次合并,以将这些文件合并成一个大的有序文件。
  • 对于ReduceTask,它从每个MapTak上远程拷贝相应的数据文件,如果文件大小超过一定阑值,则放到磁盘上,否则放到内存中。如果磁盘上文件数目达到一定阈值,则进行一次合并以生成一个更大文件;如果内存中文件大小或者数目超过一定阈值,则进行一次合并后将数据写到磁盘上。当所有数据拷贝完毕后,ReduceTask统一对内存和磁盘上的所有数据进行一次归并排序。
  • 排序器:排序器影响的是排序的速度(效率,对什么排序?),QuickSorter
  • 比较器:比较器影响的是排序的结果(按照什么规则排序)

获取Mapper输出的key的比较器(源码)

  1. public RawComparator getOutputKeyComparator() {
  2. // 从配置中获取mapreduce.job.output.key.comparator.class的值,必须是RawComparator类型,如果没有配置,默认为null
  3. Class<? extends RawComparator> theClass = getClass(JobContext.KEY_COMPARATOR, null, RawComparator.class);
  4. // 一旦用户配置了此参数,实例化一个用户自定义的比较器实例
  5. if (theClass != null){
  6. return ReflectionUtils.newInstance(theClass, this);
  7. }
  8. //用户没有配置,判断Mapper输出的key的类型是否是WritableComparable的子类,如果不是,就抛异常,如果是,系统会自动为我们提供一个key的比较器
  9. return WritableComparator.get(getMapOutputKeyClass().asSubclass(WritableComparable.class), this);
  10. }

案例实操(区内排序)

需求

对每个手机号按照上行流量和下行流量的总和进行内部排序。



思考

因为Map Task和ReduceTask均会默认对数据按照key进行排序,所以需要把流量总和设置为Key,手机号等其他内容设置为value

FlowBeanMapper.java

  1. public class FlowBeanMapper extends Mapper<LongWritable, Text, LongWritable, Text>{
  2. private LongWritable out_key=new LongWritable();
  3. private Text out_value=new Text();
  4. @Override
  5. protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
  6. String[] words = value.toString().split("\t");
  7. //封装总流量为key
  8. out_key.set(Long.parseLong(words[3]));//切分后,流量和的下标为3
  9. //封装其他内容为value
  10. out_value.set(words[0]+"\t"+words[1]+"\t"+words[2]);
  11. context.write(out_key, out_value);
  12. }
  13. }

FlowBeanReducer.java

  1. public class FlowBeanReducer extends Reducer<LongWritable, Text, Text, LongWritable>{
  2. @Override
  3. protected void reduce(LongWritable key, Iterable<Text> values,
  4. Reducer<LongWritable, Text, Text, LongWritable>.Context context) throws IOException, InterruptedException {
  5. for (Text value : values) {
  6. context.write(value, key);
  7. }
  8. }
  9. }

FlowBeanDriver.java

  1. public class FlowBeanDriver {
  2. public static void main(String[] args) throws Exception {
  3. Path inputPath=new Path("E:\\mroutput\\flowbean");
  4. Path outputPath=new Path("e:/mroutput/flowbeanSort1");
  5. //作为整个Job的配置
  6. Configuration conf = new Configuration();
  7. //保证输出目录不存在
  8. FileSystem fs=FileSystem.get(conf);
  9. if (fs.exists(outputPath)) {
  10. fs.delete(outputPath, true);
  11. }
  12. // ①创建Job
  13. Job job = Job.getInstance(conf);
  14. // ②设置Job
  15. // 设置Job运行的Mapper,Reducer类型,Mapper,Reducer输出的key-value类型
  16. job.setMapperClass(FlowBeanMapper.class);
  17. job.setReducerClass(FlowBeanReducer.class);
  18. // Job需要根据Mapper和Reducer输出的Key-value类型准备序列化器,通过序列化器对输出的key-value进行序列化和反序列化
  19. // 如果Mapper和Reducer输出的Key-value类型一致,直接设置Job最终的输出类型
  20. //由于Mapper和Reducer输出的Key-value类型不一致(maper输出类型是long-text,而reducer是text-value)
  21. //所以需要额外设定
  22. job.setMapOutputKeyClass(LongWritable.class);
  23. job.setMapOutputValueClass(Text.class);
  24. job.setOutputKeyClass(Text.class);
  25. job.setOutputValueClass(LongWritable.class);
  26. // 设置输入目录和输出目录
  27. FileInputFormat.setInputPaths(job, inputPath);
  28. FileOutputFormat.setOutputPath(job, outputPath);
  29. // 默认升序排,可以设置使用自定义的比较器
  30. //job.setSortComparatorClass(DecreasingComparator.class);
  31. // ③运行Job
  32. job.waitForCompletion(true);
  33. }
  34. }

运行结果(默认升序排)

自定义排序器,使用降序

  • 方法一:自定义类,这个类必须是RawComparator类型,通过设置mapreduce.job.output.key.comparator.class自定义的类的类型。

    自定义类时,可以继承WriableComparator类,也可以实现RawCompartor

    调用方法时,先调用RawCompartor. compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2),再调用RawCompartor.compare()

  • 方法二:定义Mapper输出的key,让key实现WritableComparable,实现CompareTo()

MyDescComparator.java

  1. public class MyDescComparator extends WritableComparator{
  2. @Override
  3. public int compare(byte[] b1, int s1, int l1,byte[] b2, int s2, int l2) {
  4. long thisValue = readLong(b1, s1);
  5. long thatValue = readLong(b2, s2);
  6. //这里把第一个-1改成1,把第二个1改成-1,就是降序排
  7. return (thisValue<thatValue ? 1 : (thisValue==thatValue ? 0 : -1));
  8. }
  9. }

运行结果

MapReduce之WritableComparable排序的更多相关文章

  1. Hadoop(18)-MapReduce框架原理-WritableComparable排序和GroupingComparator分组

    1.排序概述 2.排序分类 3.WritableComparable案例 这个文件,是大数据-Hadoop生态(12)-Hadoop序列化和源码追踪的输出文件,可以看到,文件根据key,也就是手机号进 ...

  2. Hadoop学习笔记—11.MapReduce中的排序和分组

    一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排 ...

  3. Hadoop学习笔记: MapReduce二次排序

    本文给出一个实现MapReduce二次排序的例子 package SortTest; import java.io.DataInput; import java.io.DataOutput; impo ...

  4. (转)MapReduce二次排序

    一.概述 MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的.在我们实际的需求当中,往往有要对reduce输出结果进行二次排序的需求 ...

  5. 详细讲解MapReduce二次排序过程

    我在15年处理大数据的时候还都是使用MapReduce, 随着时间的推移, 计算工具的发展, 内存越来越便宜, 计算方式也有了极大的改变. 到现在再做大数据开发的好多同学都是直接使用spark, hi ...

  6. mapreduce数据处理——统计排序

    接上篇https://www.cnblogs.com/sengzhao666/p/11850849.html 2.数据处理: ·统计最受欢迎的视频/文章的Top10访问次数 (id) ·按照地市统计最 ...

  7. mapreduce 实现数子排序

    设计思路: 使用mapreduce的默认排序,按照key值进行排序的,如果key为封装int的IntWritable类型,那么MapReduce按照数字大小对key排序,如果key为封装为String ...

  8. MapReduce二次排序

    默认情况下,Map 输出的结果会对 Key 进行默认的排序,但是有时候需要对 Key 排序的同时再对 Value 进行排序,这时候就要用到二次排序了.下面让我们来介绍一下什么是二次排序. 二次排序原理 ...

  9. Hadoop MapReduce 二次排序原理及其应用

    关于二次排序主要涉及到这么几个东西: 在0.20.0 以前使用的是 setPartitionerClass setOutputkeyComparatorClass setOutputValueGrou ...

随机推荐

  1. Nginx平滑升级详细步骤-113p.cn

    认识平滑升级 有时候我们需要对Nginx版本进行升级以满足运维人员对其功能的需求,例如添加xxx模块,需要xxx功能,而此时Nginx又在跑着业务无法停掉,这时我们就只能平滑升级了. 平滑升级原理 N ...

  2. 12 . Kubernetes之Statefulset 和 Operator

    Statefulset简介 k8s权威指南这样介绍的 "在Kubernetes系统中,Pod的管理对象RC.Deployment.DaemonSet和Job都面向无状态的服务.但现实中有很多 ...

  3. css3 pointer-events(阻止hover、active、onclick等触发事件)

    pointer-events CSS 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的 target. /* Keyword values */ pointer-events: ...

  4. 基础设计模式-02 UML图

    在学习设计模式的时候,经常会涉及到类,接口之间关系的梳理,UML图就是一个很好的方式: 1.类,抽象类,接口 类: 抽象类: 接口: 1.抽象类斜体表示: 2.“+”表示public,"-& ...

  5. 6.26模拟赛(1)总结(T1:信息传递;T2:传染病控制;T3:排列;T4:最大数)

    16:33:56 2020-06-26 当然可以先看一下成绩: 非常显然的成绩不能算有多好,当然其实这也可能是假期水课的报应  (额) 但是比我集训前想象的要好一点(集训时想象的是排名前30就可以,嗯 ...

  6. P2585 三色二叉树 题解

    题目 一棵二叉树可以按照如下规则表示成一个由0.1.2组成的字符序列,我们称之为"二叉树序列S": \[S=\left\{ \begin{aligned} 0 &\ \ 表 ...

  7. python入门005

    垃圾回收机制详解(了解) 1.引用计数 x = 10 # 直接引用 print(id(x)) y = x z = x l = ['a', 'b', x] # 间接引用 print(id(l[2])) ...

  8. Howdoo中文社区AMA总结(10月21日)

    10月21日Howdoo举办了中文社区的首次AMA活动,CEO -David Brierley和CMO -Jason Sibley加入到社群中与大家交流并回答社区成员的相关问题. 以下是精选的问题总结 ...

  9. 0ctf_2016 _Web_unserialize

    0x01 拿到题目第一件事是进行目录扫描,看看都有哪些目录,结果如下: 不少,首先有源码,我们直接下载下来,因为有源码去分析比什么都没有更容易分析出漏洞所在. 通过这个知道,它一共有这么几个页面,首页 ...

  10. shell专题(十一):企业真实面试题(重点)

    11.1 京东 问题1:使用Linux命令查询file1中空行所在的行号 答案: [atguigu@hadoop102 datas]$ awk '/^$/{print NR}' sed.txt 问题2 ...