【3-5】mapreduce例子【未解决】

本文介绍了一种使用Hadoop MapReduce技术统计特定手机号在指定时间段内的上行和下行流量的方法。通过定义自定义bin和封装字段信息到DataBean对象,实现了按照手机号分组统计流量。此外,文章详细解释了在Linux环境下使用Eclipse配置Maven和编写MapReduce程序的步骤,包括下载依赖、配置pom.xml文件、实现Mapper和Reducer类等关键步骤。最终,通过上传数据到Hadoop并执行程序,得到了每个手机号在该时间段内的总流量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的:统计某个手机号在某个时间段内产生多少流量。


文件在

一共11个字段,需要知道 时间【本例数据太少,基本全加】,手机号,流量上行,流量下行,其实就是三个字段。


数据准备:把谁作为key,把谁作为value?【我要按照手机号分组的啊!类似Wordcount一样,hello 5次,Jerry 1次。我们可以把属性封装为一个对象里(类似c语言的结构体)。

这是个封装的思想】因此,我们首先应该定义一个bin,实现Writable接口。

为了模拟真实的生产环境,我们使用maven,(当然有一些公司要求必须在Linux下开发),Windows和Linux的Java分隔符是不一样的。


这个mapreduce在Linux下开发,以后在Linux下开发要使用Linux的图形界面,要在图形界面上安装eclipse。首先将eclipse上传

首先下载一个适合虚拟机的eclipse-jee-linux.tar.gz

之后tar -zxvf eclipse-jee.tar.gz -C /usr/local/ 把它解压到这个文件夹里

然后,创建一个快捷方式,桌面上右键——创建启动器——之后在路径里面选择usr/local/eclipse,然后点选里面的eclipse。桌面上的图片也可以换;如果不换是一个小弹簧,换的话同样在eclipse那个文件夹里面找,最下面就是一张图片,双击即可。

打开eclipse,选择workbench,之后在project explorer里面右键——创建一个project——然后点击文件夹maven——选择maven project——勾选“create a simple project ”


GAV听老师说,是所谓的“坐标”


点finish之后,发现有问题,我的虚拟机不能上网,需要maven的一些依赖,于是我们手动下载maven需要的包m2.tar.gz

之后放在虚拟机里解压 tar -zxvf m2.tar.gz

之后,先更新maven,右键datacount——maven——update maven


我并没有安装maven程序,因为eclipse自带了maven的插件,下载了m2文件,在目录里解压之后,无法右键——maven——update project,我这里报错了


百度了好多方法,也没能解决,求大神。。。


http://www.oschina.net/question/2263364_220988?sort=time

有人说了是没配置myeclipse。我准备看看。。如何配置。。


后来,我机智的放弃了。。。我选择了用Windows里的eclipse来玩。因为Windows里能联网,直接能配置好maven

看到这个标志,就是maven配置好的样子了


正常情况下,上面带个叉,是不行的,后来联网后,那个×变成了叹号! 就是可以了。

接下来,第一步是配置pom文件。

双击,点pom.xml。 出现是这样的


【后续】:我后来试了好几次,无论如何也在Linux上安装不成这个datacount,后来,我按照txt上的说明,先下载了maven的安装包,然后再解压maven的包,再配置maven的环境变量,再配置xml,再安装eclipse,再把.m2.tar.gz解压到root根目录下,成功了。

我怀疑上次失败的原因有两点:第一是没有安装maven,第二是因为解压.m2次数过多,产生了太多次的lastUpdate文件删不干净【网上有人说必须全删了才能成功,但是我电脑搜索起来太费时间】。最后的方式是记得给虚拟机快照。。我后来重新回到了之前的快照,然后再干干净净地弄一次,才成功的。。

还有第三点!我怀疑是解压.m2位置的关系,如果你是root用户,你就解压到/root/下面,如果你是哪个用户就解压到哪个下面,也可能是这个位置的原因

所以在这儿也有个教训。。没事儿记得多给虚拟机拍快照。。


好啦 接下来继续往下走,第一步继续配置pom.xml文件


dependencies,hadoop-common包,不管你是用mapreduce还是hdfs,都要引用的,


此时,我左边的maven dependencies里面还是啥都没有,我一Ctrl+s就都有了,这些都是maven的依赖


由于我们要开发mapreduce程序,因此还要增加hadoop-mapreduce-client-core依赖

<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.2.0</version>
</dependency>

【项目经理特喜欢】

接下来,要写mapreduce程序了,新建一个class


包名和类名如图所示

注意:Linux下面的eclipse和Windows下面的eclipse有一点点小区别,快捷键有可能不一样,这样的话,要去Windows——preference——keys——content assist里面改


map阶段干什么?把字段拆分,之后封装在对象里面,(一次上网信息我封装在DataBean里面)


接下来reduce阶段,key是手机号,value是4个DataBean的集合,我对DataBean里的数据进行求和

代码如下:

package cn.itcast.hadoop.mr.dc;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Mapper.Context;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.jobhistory.ReduceAttemptFinished;

public class DataCount {

	public static void main(String[] args) {
		// 最后,写它的入口程序
		Configuration conf =new Configuration();
		Job job = Job.getInstance(conf);
		//我的configuration要对job进行个性化配置,不配置的话MR会读全局到信息
		job.setJarByClass(DataCount.class);
		//把main方法所在的类设上去
		job.setMapperClass(DCMapper.class);
		//在k2k3 v2v3类型一样到时候,下面两个可以省略
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(DataBean.class);
		//args可以接收数组
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		
		job.setReducerClass(DCReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(DataBean.class);
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		
		job.waitForCompletion(true);//等待把详情打印出来
		
		
		
	}

	//首先计算我的输入和输出,先看一下我到输入文件和输出接口
	//首先定义一个类,继承mapper,确定四个泛型
	public static class DCMapper extends Mapper<LongWritable, Text, Text, DataBean>

		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
			//实现map方法
			//十一个字段,key所偏移量,value是一行内容
		String line = value.toString();
		String[] fields = line.split("\t");
		String telNo = fields[1];
		long up = Long.parseLong(fields[8]);
		long down = Long.parseLong(fields[9]);
		//然后是传递,由于不能一下子传递这么多数据,因此封装到bean里边
		DataBean bean = new DataBean(telNo,up,down);
		context.write(new Text(telNo), bean);
		}
	//如上所言,我定义类一个静态内部类,四个泛型分别代表mapper的输入和输出,K1V1K2V2
	//k1我们用不上,还是longwritable,V1由于所文本类型,每行代表一个文本输出,因此是TEXT,k2,我们按照手机号来分组,可以统计流量。手机号也是text类型。我们自己定义一个databean
	//我自己写一个databean,这个一定要实现wiritable接口
	//写完databean类之后,我下一步可以在这个类里面重写map方法了
	
}
	public static class DCReducer extends Reducer<Text, DataBean, Text, DataBean>{

		@Override
		protected void reduce(Text key, Iterable<DataBean> v2s,
			Context context)
				throws IOException, InterruptedException {
			//跟wordcount一样
			long up_sum = 0;
			long down_sum = 0;
			for(DataBean bean:v2s){
				up_sum +=bean.getUpPayLoad();
				down_sum += bean.getDownPayLoad();
			}
			DataBean bean = new DataBean("",up_sum,down_sum);
			context.write(key, bean);
			
			
		}
		
	}

后面是自己定义的DataBean的代码:

package cn.itcast.hadoop.mr.dc;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.Writable;

public class DataBean implements Writable{

	private String telNo;
	private long upPayLoad;
	private long downPayLoad;
	private long totalPayLoad;
	//我为了赋值方便,添加一个有参的构造方法
	//添加里一个有参的构造方法之后最好还要添加一个无参的构造方法
		public DataBean(){}
		//没有返回值,构造方法名与类名相同,说明是一个构造方法
		public DataBean(String telNo, long upPayLoad, long downPayLoad) {
			
			this.telNo = telNo;
			this.upPayLoad = upPayLoad;
			this.downPayLoad = downPayLoad;
			this.totalPayLoad = upPayLoad + downPayLoad;
			
		}
	
	
	
	//序列化:将内存(对象)里到信息放在字节流里
	//注意:1.序列和反序列化顺序要一致.2 类型(手机号用UTF)
	public void write(DataOutput out) throws IOException {
		// TODO Auto-generated method stub
		out.writeUTF(telNo);
		out.writeLong(upPayLoad);
		out.writeLong(downPayLoad);
		out.writeLong(totalPayLoad);
		
	}
	
	//反序列化:将字节流里到内容读出来给对象赋值
	public void readFields(DataInput in) throws IOException {
		// TODO Auto-generated method stub
		this.telNo = in.readUTF();
		this.upPayLoad = in.readLong();
		this.downPayLoad = in.readLong();
		this.totalPayLoad = in.readLong();
		
	}
	//重写toString方法
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return this.upPayLoad  + "\t" + this.downPayLoad;
	}
	
	
	public String getTelNo() {
		return telNo;
	}
	
	public void setTelNo(String telNo) {
		this.telNo = telNo;
	}
	public long getUpPayLoad() {
		return upPayLoad;
	}
	public void setUpPayLoad(long upPayLoad) {
		this.upPayLoad = upPayLoad;
	}
	public long getDownPayLoad() {
		return downPayLoad;
	}
	public void setDownPayLoad(long downPayLoad) {
		this.downPayLoad = downPayLoad;
	}
	public long getTotalPayLoad() {
		return totalPayLoad;
	}
	public void setTotalPayLoad(long totalPayLoad) {
		this.totalPayLoad = totalPayLoad;
	}

}

之后在hadoop上面上传HTTP那个文件,之后把这个两个Java打成jar包,放在/root/examples里面,然后就在hadoop里可以打开,


很遗憾,我的mapreduce并没有运行成功。我也不知道为什么。。不过我心好累。。先消化消化这些代码吧。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值