从Top N 问题窥探MapReduce分组前排序思想

分组Top N问题(二) - Hadoop MapReduce实现 前言: 在Hadoop中,排序是MapReduce的灵魂,MapTask和ReduceTask均会对数据按Key排序,这个操作是MR框架的默认行为,不管你的业务逻辑上是否需要这一操作。 技术点: MapReduce框架中,用到的排序主要有两种:快速排序和基于堆实现的优先级队列(PriorityQueue)。 Mapper阶段:  从map输出到环形缓冲区的数据会被排序(这是MR框架中改良 阅读详情

#博学谷IT学习技术支持#

关于TopN 问题中的排序

  案例:
  现有美国2021-1-28号,各个县county的新冠疫情累计案例信息,包括确诊病例和死亡病例,数据格式如下所示:

2021-01-28,Juneau City and Borough,Alaska,02110,1108,3
2021-01-28,Kenai Peninsula Borough,Alaska,02122,3866,18
2021-01-28,Ketchikan Gateway Borough,Alaska,02130,272,1
2021-01-28,Kodiak Island Borough,Alaska,02150,1021,5
2021-01-28,Kusilvak Census Area,Alaska,02158,1099,3
2021-01-28,Lake and Peninsula Borough,Alaska,02164,5,0
2021-01-28,Matanuska-Susitna Borough,Alaska,02170,7406,27
2021-01-28,Nome Census Area,Alaska,02180,307,0
2021-01-28,North Slope Borough,Alaska,02185,973,3
2021-01-28,Northwest Arctic Borough,Alaska,02188,567,1
2021-01-28,Petersburg Borough,Alaska,02195,43,0
字段含义如下:date(日期),county(县),state(州),fips(县编码code),cases(累计确诊病例),deaths(累计死亡病例)。
需求:找出美国2021-01-28,每个州state的确诊案例数最多的县county前3个。Top3问题。

上面的问题中,我们使用MapReduce编码实现,其思路是需要按照州名进行分组,然后每个州内按照确诊病例数进行倒序排序。因此需要定义一个JavaBean对象,实现WriteComparable接口,重写compareTo方法;同时需要自定义分组规则,将州名相同的数据分到同一组。
Mapper类代码如下:

public class CovidTopMapper extends
        Mapper<LongWritable, Text, CovidBean, NullWritable> {

    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        String[] splitArr = value.toString().split(",");
        CovidBean covidBean = new CovidBean();
        covidBean.setDate(splitArr[0]);
        covidBean.setCounty(splitArr[1]);
        covidBean.setState(splitArr[2]);
        covidBean.setCode(splitArr[3]);
        covidBean.setCases(Integer.valueOf(splitArr[4]));
        covidBean.setDeaths(splitArr.length > 5 ? Integer.valueOf(splitArr[5]) : 0);
        context.write(covidBean, NullWritable.get());
    }
}

Reducer类代码如下:

public class CovidTopReducer
        extends Reducer<CovidBean, NullWritable, CovidBean, NullWritable> {

    @Override
    protected void reduce(CovidBean key, Iterable<NullWritable> values, Context context)
            throws IOException, InterruptedException {
        int i = 0;
        for (NullWritable value : values) {
            if (i > 2) {
                break;
            }
            context.write(key, value);
            i++;
        }

    }
}

JavaBean定义:

@Data
public class CovidBean implements WritableComparable<CovidBean> {

    private String date;
    private String county;
    private String state;
    private String code;
    private int cases;
    private int deaths;



    @Override
    public void write(DataOutput out) throws IOException {
        out.writeUTF(date);
        out.writeUTF(county);
        out.writeUTF(state);
        out.writeUTF(code);
        out.writeInt(cases);
        out.writeInt(deaths);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        this.date = in.readUTF();
        this.county = in.readUTF();
        this.state = in.readUTF();
        this.code = in.readUTF();
        this.cases = in.readInt();
        this.deaths = in.readInt();
    }

    @Override
    public String toString() {
        return  county + '\t'
                + state + '\t'
                + cases + '\t'
                + deaths;
    }

    @Override
    public int compareTo(CovidBean o) {
        return this.getState().compareTo(o.getState()) == 0 ?
                -(this.getCases() - o.getCases()) : this.getState().compareTo(o.getState());
//        return o.getCases() - this.getCases();
    }
}

执行结果:
在这里插入图片描述

在JavaBean定义中,我们实现的排序比较规则是先按照州名排序,然后再按照确诊病例数排序。可能会有疑惑的地方是为什么需要先按照州名进行排序,而不是直接按照确诊病例数进行排序呢?
MapReduce中规定分组字段,必须是排序字段,必须保证分组前数据是有序的,这样才能保证指定分组规则的数据分到同一组。假设我们只按照确诊病例数进行排序,而不首先按照州名进行排序。我们得到的结果是没有分组的结果,是按照确诊病例数进行全局排序的结果,如下:

在这里插入图片描述
发现和我们预期的结果不同,那么是什么原因导致了这种结果呢,接下来我们就通过分析MapReduce源码,来探究MapReduce分组前排序思想的实现。

MapReduce源码分析分组前排序原理

在TopN案例中,使用了自定义分组比较器,重写了分组比较的逻辑。
从MapReduce执行过程来看,首先是执行Map任务,然后经过Shuffle阶段的分区、排序、分组,最后执行Reduce任务。查看Reducer类源码,在执行reduce方法之前,首先会按照Key对数据进行分组,如下所示:

 public void run(Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT>.Context context) throws IOException, InterruptedException {
        this.setup(context);

        try {
            while(context.nextKey()) {
                this.reduce(context.getCurrentKey(), context.getValues(), context);
                Iterator<VALUEIN> iter = context.getValues().iterator();
                if (iter instanceof ValueIterator) {
                    ((ValueIterator)iter).resetBackupStore();
                }
            }
        } finally {
            this.cleanup(context);
        }

    }

通过进一步查看context.nextKey的实现,我们发现,迭代器在遍历每一对key和value时,会将当前key和下一个key进行比较,如果相同的话,则会循环遍历,直到下一个key值不相同,退出循环,然后执行reduce方法,在reduce方法中就取到了所有key划分为同一组的值。在这种情况下,始终是将当前值和下一个值进行比较,因此,如果数据没有按照分组的字段进行有序的排列,那么nextKeyIsSame的值为false,循环退出,执行reduce方法,从而导致本应该划分为同一组的key、value键值对被打散,无法实现分组的效果。

  public boolean nextKey() throws IOException, InterruptedException {
        while(this.hasMore && this.nextKeyIsSame) {
            this.nextKeyValue();
        }

        if (this.hasMore) {
            if (this.inputKeyCounter != null) {
                this.inputKeyCounter.increment(1L);
            }

            return this.nextKeyValue();
        } else {
            return false;
        }
    }
    public boolean nextKeyValue() throws IOException, InterruptedException {
        if (!this.hasMore) {
            this.key = null;
            this.value = null;
            return false;
        } else {
            this.firstValue = !this.nextKeyIsSame;
            DataInputBuffer nextKey = this.input.getKey();
            this.currentRawKey.set(nextKey.getData(), nextKey.getPosition(), nextKey.getLength() - nextKey.getPosition());
            this.buffer.reset(this.currentRawKey.getBytes(), 0, this.currentRawKey.getLength());
            this.key = this.keyDeserializer.deserialize(this.key);
            DataInputBuffer nextVal = this.input.getValue();
            this.buffer.reset(nextVal.getData(), nextVal.getPosition(), nextVal.getLength() - nextVal.getPosition());
            this.value = this.valueDeserializer.deserialize(this.value);
            this.currentKeyLength = nextKey.getLength() - nextKey.getPosition();
            this.currentValueLength = nextVal.getLength() - nextVal.getPosition();
            if (this.isMarked) {
                this.backupStore.write(nextKey, nextVal);
            }

            this.hasMore = this.input.next();
            if (this.hasMore) {
                nextKey = this.input.getKey();
                this.nextKeyIsSame = this.comparator.compare(this.currentRawKey.getBytes(), 0, this.currentRawKey.getLength(), nextKey.getData(), nextKey.getPosition(), nextKey.getLength() - nextKey.getPosition()) == 0;
            } else {
                this.nextKeyIsSame = false;
            }

            this.inputValueCounter.increment(1L);
            return true;
        }
    }

以案例中的TopN问题为例,我们希望同一个州的数据分到同一组中,于是我们自定义了分组比较器,比较不同Key的州名是否相等。仅仅定义了分组比较规则就够了吗?从实验的结果来看,我们还必须保证同一个州的数据在相邻的位置上,这样我们nextKeyIsSame的值才能为true,保证相同州的数据分到同一组中,执行同一次reduce方法。为了保证同一个州的数据在相邻位置,那么就必须按照州名进行排序。而为了在同一组中取到TopN的数据,我们必须按照确诊病例对同一州的数据进行排序。
因此,在MapReduce编程模型中,我们需要按照某字段进行分组,必须首先按照该字段进行排序。

【信息科学与工程学】【运营科学】第二篇 C4信息与通信网络运营 (C4) ——数据中心网络运营04 典型值:λ1​∈[−0.02,−0.01], λ2​∈[−0.01,0], η1​,η3​∈[0.1,0.3], η2​,η4​∈[0.05,0.15]参数:δ1​∈[−0.8,−0.3], δ2​∈[−0.5,−0.2], δ3​∈[−0.4,−0.1], δ4​∈[−0.6,−0.2]参数:φ1​∈[0.1,0.3], φ2​∈[−0.2,−0.05], φ3​∈[−0.1,0.1], φ4​∈[−0.3,−0.1]参数:α∈[0.3,0.6], β∈[0.2,0.4], γ∈[0.01,0.03] 阅读详情

相关推荐

【信息科学与工程学】【数据中心】第三十二篇 云数据中心的计算/存储/网络的核心挑战01

状态方程: SOCk+1​=SOCk​−Qn​ik​Δt​;: 三相电流变换到αβ坐标系: iα​=32​​(ia​−21​ib​−21​ic​), iβ​=32​​(23​​ib​−23​​ic​). 计算瞬时有功功率p和无功功率q,经低通滤波器分离直流分量,反变换得基波电流,差值即为谐波指令。: 节点i的信念 bi​(xi​)=ϕi​(xi​)∏j∈N(i)​mji​(xi​), 消息 mij​(xj​)=∑xi​​ϕi​(xi​)ψij​(xi​,xj​)∏k∈N(i)\j​mki​(xi​).

weixin_49199313的博客 221

美国新冠疫情病例统计

美国新冠疫情病例统计MapReduce实现

m0_56525833的博客 571

【信息科学与工程学】【数据科学】第一百二十二篇 大数据产品中的函数与算法01

它通常指。下面按照你给出的表格列💡 说明:下表中的"产品"以开源/主流商业组件为具象载体(Hadoop、Spark、Flink、Kafka、Hive、HBase、Iceberg、Atlas、Ranger、TensorFlow 等),它们共同构成一个完整的大数据产品家族;代码为实现示例,用于说明算法在工程系统中的落地方式。

weixin_49199313的博客 200

彷徨 | MapReduce实例五 | MapReduce求TopN的三种方法 , 以电影数据为例

本文采用三种方式对movie数据进行TopN排序 第一种是直接排序,在ReduceTask中进行排序 第二种是利用Tree排序,该方式利用小顶堆和集合重复原理的方式 , 每过来一个数据 , 跟堆顶数据进行比较 , 如果比最小的大 , 则 =踢掉换新的 , 否则直接跳过数据 . 以此对数据进行排序 .  第三种是利用MepReduce高级API编程,定义分区器和分组比较器. 数据样本: {"m...

彷徨的博客 3642

美国新冠疫情累计测试案例数据集

各个县county的新冠疫情累计案例信息,包括确诊病例和死亡病例。字段含义如下:date(日期),county(县),state(州),fips(县编码code),cases(累计确诊病例),deaths(累计死亡病例)。

基于plc的工厂除尘控制系统设计(S7-200、仿真、调试、高质量)

工业作为我国第二支柱产业,在近十几年来发展非常迅速,虽然带了了可观的经济效益,但在工业生产中所产生的大量粉尘气体对大气的污染现象也不容忽视。为减少工业粉尘对环境的污染,世界各国制定了严格的环境保护要求。为了减少工业中粉尘的排放,除尘器的研发改良,以及燃煤的使用等等都在不断更改以符合粉尘排放标准。而目前最先进的除尘设备无机膜除尘器具备除尘效率高,稳定性好,结构紧凑易于维护等优点,且无机膜对于粉尘吸附效率高,抗腐蚀能力优秀,耐高温,因此能更有效应用于高温烟气的除尘。本文根据PLC技术在除尘方面的应用,来优化设计

老高的博客 1282

如何使用MapReduce实现TopN

输出流量使用量在前10的用户信息:数据源: 13470253144 180 180 360 13509468723 7335 110349 117684 13560439638 918 4938 5856 13568436656 3597 25635 29232 13590439668 1116 954 2070 13630577991 6960 690 7650 13682846555 19...

isea_you's blog 1814

2023西工大NOJ (C语言版) 完结!!!

代码均可AC,不含解析。

annesede的博客 8万+

电商数据分析策略研究报告

电商数据分析策略研究报告

姜穆澜的博客 513

A-Level经济例题解析及练习Opportunity Cost

例题Question: Opportunity CostYou are selling your 1996 Mustang.&nbsp; You have already spent $1000 on repairs.&nbsp;At the last minute, the transmission dies.&nbsp; You can pay $600 to have it repaired, or sell the car “as is.”In each of the fol

Alevel3的博客 747

一个服务如何被找到、被调用、被看见:注册中心、发布注册、发现调用与服务监控的治理闭环

服务数量一多,“对方在哪儿”就成了时刻变化的变量。本文沿发布、注册、发现、调用、监控的治理闭环展开:注册中心的数据模型、健康检查与AP/CP取舍,自我保护、推空保护与本地快照三道自保机制;服务发布的启动器、动态代理、发布管理器、协议服务器与登记顺序;消费端的服务目录、请求ID配对、六种集群容错与三种发现模式;日志、指标、链路三支柱与熔断舱壁。配套五个Java演示程序实测:默认参数下宕机实例平均240秒才被摘除,优雅下线可降至45秒,统计窗口长于租约会让自我保护失效,尾部采样可捕获全部慢请求。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 169万+

用Hadoop中MapReduce进行TopN排序

数据格式: 10,3333,10,100 11,9321,1000,293 12,3881,701,20 13,6974,910,30 14,8888,11,39 订单ID 用户ID 资费 业务ID 在所有订单数据中计算出资费最高的N个订单,按降序排列 算法思想:在大量的数据中计算出资费最高的N个订单,为了节省资源和提高计算效率:在众多的Mapper的端,首先计算出自己的TopN,然后在...

someby的博客 2851

使用xlwings在Python中对Excel表格进行操作是非常方便的,可以实现自动化处理、批量数据处理等功能

使用xlwings在Python中对Excel表格进行操作是非常方便的,可以实现自动化处理、批量数据处理等功能。本篇文章主要介绍如何使用xlwings对Excel表格进行多行多列数据设置和操作,并给出相应的源代码。接着,我们可以对这个范围内的所有单元格进行操作,如设置字体颜色、填充颜色、对齐方式等。以上就是使用xlwings对Excel表格进行多行多列数据操作和设置字体颜色、填充色和对齐方式的全部内容。最后,我们可以将数据写入到单元格中,也可以从单元格中读取数据。在Excel中,可以通过。

BUG?不存在的! 714

Hadoop3 - MapReduce COVID-19 案例实践

COVID-19,简称“新冠肺炎”,世界卫生组织命名为“2019冠状病毒病” [1-2] ,是指2019新型冠状病毒感染导致的肺炎。方法用于将当前对象与方法的参数进行比较。如果指定的数与参数相等返回0。如果指定的数小于参数返回 -1。如果指定的数大于参数返回 1。数据集目录和输出目录通过参数传递进来,这里我将数据集放在了。实现排序的效果,不过在上面我们已经实现了。创建 Mapper 类,截取出。输出的结果在进行处理,利用。创建 Reducer ,对。接口,在上篇文章中就讲到。, 无需做任何操作直接。

小毕超博客 1907

Far planner 部署真实小车 & 树莓派部署lego_loam

今天开一贴Far planner的部署,也算是lego loam的部署吧 因为state_estimation用的是lego loam小车底盘: 轮趣的mini差速底盘外加多一层钢板,中间层用来放velodyne的电池(小的电池还没到,大的电池塞不进去目前)和velodyne信号盒子。前面还可以加一个相机。底层用来放小车的电池和马达等设备了,底层不用动。最上面一层用来安装velodyne16线雷达,需要额外钻孔(如果买轮趣的话可以找老板钻个孔?我也不确定,我自己钻的)。 雷达固定螺丝用的是 1/4-20*3

博客 4303

腾讯Android高级开发工程师面试指南与参考答案

腾讯深圳元宝高级Android开发工程师岗位招聘,要求3-5年Android开发经验,熟悉Kotlin、性能优化和架构设计。岗位职责包括元宝App架构研发、稳定性优化及跨团队协作。面试分3轮,流程较快,主要考察技术能力(Kotlin、算法)、架构设计及项目经验。重点准备性能优化案例、多线程编程及Compose开发等加分项。无AI项目经验也可应聘,需突出Android开发能力。建议复习MVVM架构、JNI等技术,并准备项目优化案例。

郑伟强dev的专栏 1647

大数据学习笔记-MapReduce(二) 深度

深度了解MapReduce运行流程,通过案例全面了解MR运行过程、涉及的组件、设计的思想。对MapReduce Partition、 Mapreduce Combiner、MapReduce编程技巧掌握,对自定义对象、序列化、排序、分区、分组的实现熟练掌握,掌握MapReduce并行度机制、工作流程和shuffle的机制。

zhang_232的专栏 575

基于MATLAB的逐次变分模态分解(SVMD)算法详解

本文详细介绍了基于MATLAB的逐次变分模态分解(SVMD)算法。SVMD是一种改进的变分模态分解方法,通过逐次分解机制克服传统VMD算法需要预设模态数量的缺陷。文章从信号分解方法的发展历程入手,阐述了SVMD的核心优势与创新点,包括参数敏感性降低、自适应分解能力和更好的频率分离性能。详细解析了SVMD的数学模型和优化求解过程,重点讨论了变分问题构建、ADMM优化方法和停止准则设计。通过MATLAB代码实现展示了SVMD的具体应用,包括参数初始化、信号预处理、模态提取和残余信号更新等关键步骤。

qq_42212808的博客 133

Hadoop生态圈(二十一)- MapReduce编程基础

MapReduce Partition分区,MapReduce Combiner规约,MapReduce自定义对象序列化,MapReduce自定义排序,MapReduce自定义分区,MapReduce自定义分组,自定义分组扩展:topN问题,默认情况下MR输出文件个数,数据分区概念,默认分区规则,Partition注意事项,数据规约的含义,MapReduce弊端,Combiner组件概念,Combiner组件使用,Combiner使用注意事项,MapReduce执行流程图,key的重要性体现

程序园@大Null 4488

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

MapReduce过程详解(基于hadoop2.x架构)

本文基于hadoop2.x架构详细描述了mapreduce的执行过程,包括partition,combiner,shuffle等组件以及yarn平台与mapreduce编程模型的关系。 mapreduce的简介和优点 mapreduce是一个分布式运算程序的编程框架,是hadoop数据分析的核心. mapreduce的核心思想是将用户编写的逻辑代码和架构中的各个组件整合成一个分布式运算程序,实现...

weixin_30699443的博客 487

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

关于TOPN问题与堆排序

1、TOPN问题本质就是在一个海量的数据里面取最大的N个元素的问题。然后呢,围绕这个问题,还会有其它一些问题。 2、如果这个数据量不是很大,比如100个数据,取最大的10个,那先排序

见端而知末 2421

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Hadoop编程——第五章:(6)MapReduce自定义排序案例

将美国每个州state的确诊案例数进行倒序排序。如果你的需求中需要根据某个属性进行排序,不妨把这个属性作为key。因为MapReduce中key有默认排序行为的。可使用案例1的输出结果表作为本案例的输入表。1、如果你的需求是正序,并且数据类型是Hadoop封装好的类型。这种情况下不需要任何修改,直接使用lHadoop类型作为kcy即可。因为Hadoop封装好的类型已经实现了排序规则。2、如果你的需求是倒序,或者数据类型是自定义对象。需要重写排序规则。对象实现Comparable接口重写CompareTo方法

weixin_45348240的博客 1011

大数据Hive DDL高阶建表

目录1 Hive内、外部表1.1 什么是内部表1.2 什么是外部表1.3 内部表、外部表差异1.4 如何选择内部表、外部表2 Hive分区表2.1 分区表的引入、产生背景2.2 分区表的概念、创建2.3 分区表数据加载--静态分区2.4 分区表数据加载--动态分区2.5 分区表的本质2.6 分区表的使用2.7 分区表的注意事项2.8 多重分区表3 Hive分桶表3.1 分桶表的概念3.2 分桶表的语法3.3 分桶表的创建3.4 分桶表的数据加载3.5 分桶表的使用好处4 Hive Transactional

赵广陆 616

MapReduce当中topN问题的解决方法

topN问题:马克-to-win @ 马克java社区:防盗版实名手机尾号:73203。topN问题就是输出每组中最大的一个或几个。为什么说是一个或几个呢?因为输出一个或者输出几个的算法是一样的。我们下面以输出一个为例子,做一个示范。6个订单如下:o1,p2,250.0o2,p3,500.0o2,p4,100.0o2,p5,700.0o3,p1,150.0o1,p1,200.0求出每个订单中最高...

mark_to_win的专栏 881

大数据学习——mapreduce学习topN问题

求每一个订单中成交金额最大的那一笔 top1 数据 Order_0000001,Pdt_01,222.8 Order_0000001,Pdt_05,25.8 Order_0000002,Pdt_05,325.8 Order_0000002,Pdt_03,522.8 Order_0000002,Pdt_04,122.4 Order_0000003,Pdt_01,222...

weixin_30407099的博客 2673

Hadoop编程——第五章:(5)MapReduce自定义对象序列化案例

有一份2020-12-01号美国各县county的新冠疫情统计数据,包括累计确诊病例、累计死亡病例。使用MapReduce对疫情数据进行各种分析统计。 案例背后的核心是学会自定义MapReduce各个组件。包括自定义对象、序列化、排序、分区、分组。date (日期) , county(县) , state(州 ) , fips(县编码code ) , cases(累计确诊病例) , deaths(索计死亡病例)。MapReduce自定义对象序列化 MapReduce自定义排序 MapReduce自定义分区

weixin_45348240的博客 933
上一篇: 包装类的自动装拆箱及Integer类的缓存区问题
下一篇: HBase Java API 示例
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值