文档章节

mapreduce top n

坏坏一笑
 坏坏一笑
发布于 2014/11/12 18:42
字数 986
阅读 2405
收藏 4

    在最初接触mapreduce时,top n 问题的解决办法是将mapreduce输出(排序后)放入一个集合中,取前n个,但这种写法过于简单,内存能够加载的集合的大小是有上限的,一旦数据量大,很容易出现内存溢出。
    今天在这里介绍另一种实现方式,当然这也不是最好的方式,不过正所谓一步一个脚印,迈好每一步,以后的步伐才能更坚定,哈哈说了点题外话。恩恩,以后还会有更好的方式

    需求,得到top 最大的前n条记录
    这里只给出一些核心的代码,其他job等配置的代码略

Configuration conf = new Configuration();
conf.setInt("N", 5);

    初始化job之前需要 conf.setInt("N",5); 意在在mapreduce阶段读取N,N就代表着top N
    以下是map

package com.lzz.one;
import java.io.IOException;
import java.util.Arrays;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;


/**
 * topN
* 	#orderid,userid,payment,productid
* [root@x00 hd]# cat seventeen_a.txt
* 1,9819,100,121
* 2,8918,2000,111
* 3,2813,1234,22
* 4,9100,10,1101
* 5,3210,490,111
* 6,1298,28,1211
* 7,1010,281,90
* 8,1818,9000,20
* [root@x00 hd]# cat seventeen_b.txt
* 100,3333,10,100
* 101,9321,1000,293
* 102,3881,701,20
* 103,6791,910,30
* 104,8888,11,39
 
* 预测结果:(求 Top N=5 的结果)
* 1	9000
* 2	2000
* 3	1234
* 4	1000
* 5	910
 * @author Administrator
 *
 */
public class TopNMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable>{
    int len;
    int top[];
    @Override
    public void setup(Context context) throws IOException,InterruptedException {
        len = context.getConfiguration().getInt("N", 10);
        top = new int[len+1];
    }
 
    @Override
public void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException {
    String line = value.toString();
    String arr []= line.split(",");
    if(arr != null && arr.length == 4){
        int pay = Integer.parseInt(arr[2]);
        add(pay);
    }
}


public void add(int pay){
    top[0] = pay;
    Arrays.sort(top);
}
 
@Override
public void cleanup(Context context) throws IOException,InterruptedException {
    for(int i=1;i<=len;i++){
        context.write(new IntWritable(top[i]),new IntWritable(top[i]));
    }
 }
 
}

 
 
 
 

  
  

    接下来是reduce

package com.lzz.one;

import java.io.IOException;
import java.util.Arrays;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Reducer;

public class TopNReduce extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable>{
	int len;
	int top[];
	@Override
	public void setup(Context context)
			throws IOException, InterruptedException {
		len = context.getConfiguration().getInt("N", 10);
		top = new int[len+1];
	}
	
	@Override
	public void reduce(IntWritable key, Iterable<IntWritable> values,
			Context context)
			throws IOException, InterruptedException {
		for(IntWritable val : values){
			add(val.get());
		}
	}
	
	public void add(int pay){
		top[0] = pay;
		Arrays.sort(top);
	}
	
	@Override
	public void cleanup(Context context)
			throws IOException, InterruptedException {
		for(int i=len;i>0;i--){
			context.write(new IntWritable(len-i+1),new IntWritable(top[i]));
		}
	}
}

    说一下逻辑,虽然画图比较清晰,但是时间有限,画图水平有限,只用语言来描述吧,希望能说的明白
    如果要取top 5,则应该定义一个长度为为6的数组,map所要做的事情就是将每条日志的那个需要排序的字段放入数组第一个元素中,调用Arrays.sort(Array[])方法可以将数组按照正序,从数字角度说是从小到大排序,比如第一条记录是9000,那么排序结果是[0,0,0,0,0,9000],第二条日志记录是8000,排序结果是[0,0,0,0,8000,9000],第三条日志记录是8500,排序结果是[0,0,0,8000,8500,9000],以此类推,每次放进去一个数字如果大于数组里面最小的元素,相当于将最小的覆盖掉了,也就是说数组中元素永远是拿到日志中最大的那些个记录
    ok,map将数组原封不动按照顺序输出,reduce接收到从每个map拿到的五个排好序的元素,在进行跟map一样的排序,排序后数组里面就是按照从小到大排好序的元素,将这些元素倒序输出就是最终我们要的结果了

    与之前的方式做个比较,之前的map做的事情很少,在reduce中排序后哪前5条,reduce的压力是很大的,要把所有的数据都处理一遍,而一般设置reduce的个数较少,一旦数据较多,reduce就会承受不了,悲剧了。而现在的方式巧妙的将reduce的压力转移到了map,而map是集群效应的,很多台服务器来做这件事情,减少了一台机器上的负担,每个map其实只是输出了5个元素而已,如果有5个map,其实reduce才对5*5个数据进行了操作,也就不会出现内存溢出等问题了




    


© 著作权归作者所有

坏坏一笑
粉丝 10
博文 54
码字总数 29772
作品 0
昌平
程序员
私信 提问
加载中

评论(1)

仙剑奇侠
仙剑奇侠
受教了!!!
MapReduce: 一个巨大的倒退

前言 databasecolumn 的数据库大牛们(其中包括PostgreSQL的最初伯克利领导:Michael Stonebraker)最近写了一篇评论当前如日中天的MapReduce技术的文章,引发剧烈的讨论。我抽空在这儿翻译一...

ddatsh
2011/11/04
4.6K
7
一文详解大规模数据计算处理原理及操作重点

作者介绍 李智慧,《大型网站技术架构:核心原理与案例分析》作者。曾供职于阿里巴巴与英特尔亚太研发中心,从事大型网站与大数据方面的研发工作,目前在做企业级区块链方面的开发工作。 大数...

DBAplus社群
2018/08/07
0
0
Hadoop实战之 MapReduce

私塾在线 整体课程概览 第一部分:开始云计算之旅 第二部分:初识Hadoop 第三部分:Hadoop 环境安装部署 第四部分:Hadoop Shell 基本操作介绍 第五部分:Hadoop 分布式文件系统1 第五部分:...

linni
2014/01/08
748
0
Reduce连接(reduce-side joins)

如果没有一个 map-side join 技术适合我们的数据集,那么就需要在 MapReduce 中使用 shuffle 来排序和连接两个数据集。这称为 reduce-side joins,也叫”重分区连接”。 【例】基本的重分区连...

天行自息
2018/11/04
29
0
Hadoop实例:二度人脉与好友推荐

在新浪微博、人人网等社交网站上,为了使用户在网络上认识更多的朋友,社交网站往往提供类似“你可能感兴趣的人”、“间接关注推荐”等好友推荐的功能。一直很好奇这个功能是怎么实现的。 其...

intergret
2013/01/03
7K
12

没有更多内容

加载失败,请刷新页面

加载更多

深入理解JVM - 类加载机制

类加载过程 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(...

xiaolyuh
11分钟前
57
0
脸盲症的小伙伴 测试下你的脸盲症程度

笔者在背单词的时候突然想到了一个问题,就是背单词的时候,相近的词容易混淆,例如:coast和roast,在我背诵的时候,我就很烦恼,不光是英文单词,还有汉字,例如“籍”和“藉“,我还是个中...

蛤蟆丸子
12分钟前
50
0
「网易官方」极客战记(codecombat)攻略-地牢-囚犯the-prisoner

解放囚犯,你会得到盟友。 简介 敬请期待! 默认代码 # 释放囚犯,击败守卫并夺取宝石。 # 从"Weak Door"后解救Patrick。 # 击败名为"Two"的守卫。 # 获得宝石。 概览 您可以按照名称 "Weak ...

极客战记
13分钟前
12
0
Final cut pro 10.4.4中文版本

1.双击打开dmg,点击红框图示 2.出现这个界面后直接回车 3直接将fcp拖拽到application文件夹 然后就可以直接打开了! 百度网盘地址:链接: https://pan.baidu.com/s/1Db9hXmzPV4EdR7_LxEqctA...

kylin_ink
15分钟前
32
0
jquery.validate

规则名称 类型 描述 required Boolean 设置该项内容为必填 remote Json|String 请求远程资源来校验内容有效性 minlength Number 设置内容的最少字符长度 maxlength Number 设置内容的最多字符...

愚蠢的土豆
15分钟前
129
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部