大数据学习之MapReduce编程案例二流量日志统计 10

每一个用户的统计总流量

一:编写代码之前。先了解一下hadoop中的序列化

JAVA 类型    HADOOP 类型

int           IntWritable

float       FloatWritable

long       LongWritable

double     DoubleWritable

string     Text

boolean      BooleanWritable

byte       ByteWritable

map       MapWritable

array ArrayWritable

扫描二维码关注公众号,回复: 6095874 查看本文章

1:为什么要序列化?

存储“活的对象”

2:什么是序列化?

序列化就是把内存当中的对象,转换成字节序列以便于存储和网络传输

反序列化就是将受到的字节序列或者硬盘的持久化数据,转换成内存中的对象

java的序列化->Serializable

为什么不使用java提供的序列化接口?

java的序列化是一个重量级的序列化框架,一个对象被序列化后会附带很多额外的信息(效验信息,header,继承体系等)。

不便于在网络中高效传输,所以hadoop开发了一套序列化机制(Writable),精简/高效.

为什么序列化在hadoop中很重要?

hadoop通信是通过远程调用(rpc)实现的,需要进行序列化

3:特点:

1)紧凑

2)快速

3)可拓展

4)互操作

二 代码编写:

1:准备好数据,如下

2 :先写一个序列化类

package it.dawn.YARNPra.flow流量汇总序列化;

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

import org.apache.hadoop.io.Writable;

/**
 * @author Dawn
 * @date 2019年5月2日14:44:27
 * @version 1.0
 * 
 * 封装类 数据的传输
 */
public class FlowBean implements Writable{
	
	//定义属性
	private long upFlow;//上行流量
	private long dfFlow;//下行流量
	private long flowSum;//总流量
	
	public FlowBean() {}

	//流量累加
	public FlowBean(long upFlow,long dfFlow) {
		this.upFlow=upFlow;
		this.dfFlow=dfFlow;
		this.flowSum=upFlow+dfFlow;
	}
	
	public long getUpFlow() {
		return upFlow;
	}

	public void setUpFlow(long upFlow) {
		this.upFlow = upFlow;
	}

	public long getDfFlow() {
		return dfFlow;
	}

	public void setDfFlow(long dfFlow) {
		this.dfFlow = dfFlow;
	}

	public long getFlowSum() {
		return flowSum;
	}

	public void setFlowSum(long flowSum) {
		this.flowSum = flowSum;
	}

	//反序列化
	@Override
	public void readFields(DataInput in) throws IOException {
		upFlow=in.readLong();
		dfFlow=in.readLong();
		flowSum=in.readLong();
	}
	//序列化
	@Override
	public void write(DataOutput out) throws IOException {

		out.writeLong(upFlow);
		out.writeLong(dfFlow);
		out.writeLong(flowSum);
	}

	@Override
	public String toString() {
		return upFlow + "\t" + dfFlow + "\t" + flowSum;
	}
	
	
	

}

  

3:Map阶段

package it.dawn.YARNPra.flow流量汇总序列化;

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

/**
 * @author Dawn
 * @date 2019年5月2日14:53:17
 * @version 1.0
 * 
 * 数据源:
 * 3631279850362	13726130503	00-FD-07-A4-72-B8:CMCC	120.196.100.82	www.itstaredu.com	教育网站	24	27	299	681	200
 * 
 * map输出结果:
 * 13726130503  299	681 980
 */
public class FlowCountMapper extends Mapper<LongWritable, Text, Text, FlowBean>{

	@Override
	protected void map(LongWritable key, Text value, Context context)
			throws IOException, InterruptedException {
		//1.获取数据
		String line=value.toString();
		
		//2.切割
		String[] fields=line.split("\t");
		
		//3.封装对象 拿到关键字段 数据清洗
		String phoneNum=fields[1];
		long upFlow=Long.parseLong(fields[fields.length - 3]);
		long dfFlow=Long.parseLong(fields[fields.length - 2]);
		
		//4.输出到reducer端13726130503  299	681  980
		context.write(new Text(phoneNum), new FlowBean(upFlow, dfFlow));
	}
	

}

  

4:Reduce阶段

package it.dawn.YARNPra.flow流量汇总序列化;

import java.io.IOException;

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

/**
 * @author Dawn
 * @date 2019年5月2日14:59:15
 * @version 1.0
 * 13726130503  299	681 980
 */
public class FlowCountReducer extends Reducer<Text, FlowBean, Text, FlowBean>{

	@Override
	protected void reduce(Text k3, Iterable<FlowBean> v3, Context context)
			throws IOException, InterruptedException {
		//1.相同手机号 的流量使用再次汇总
		long upFlow_sum=0;
		long dfFlow_sum=0;
		
		//2.累加
		for(FlowBean v:v3) {
			upFlow_sum+=v.getUpFlow();
			dfFlow_sum+=v.getDfFlow();
		}
		
		FlowBean rs=new FlowBean(upFlow_sum, dfFlow_sum);
		
		//3.输出
		context.write(k3, rs);
	}
	
}

  

5:编写Driver(本地Windows上运行的。懒得上传到集群上了,和本地运行的效果都一样)

package it.dawn.YARNPra.flow流量汇总序列化;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * @author Dawn
 * @date 2019年5月2日15:03:59
 * @version 1.0
 * 
 * 就在本地跑算了。方便点,其实和在虚拟机中效果一样
 */
public class FlowCountDriver {
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		
		Configuration conf=new Configuration();
		Job job=Job.getInstance(conf);
		
		job.setJarByClass(FlowCountDriver.class);
		
		job.setMapperClass(FlowCountMapper.class);
		job.setReducerClass(FlowCountReducer.class);
		
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(FlowBean.class);
		
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(FlowBean.class);
		
		FileInputFormat.setInputPaths(job, new Path("f:/temp/流量日志.dat"));
		FileOutputFormat.setOutputPath(job, new Path("/f:/temp/流量统计结果"));
		
		boolean rs=job.waitForCompletion(true);
		System.out.println(rs?"成功":"失败");
		
	}

}

  

大功告成:可以看下运行结果

晕怎么差不了图片了呀!!!!算了。直接上结果数据吧

13480253104 120 1320 1440
13502468823 735 11349 12084
13510439658 1116 954 2070
13560436326 1136 94 1230
13560436666 1136 94 1230
13560439658 918 4938 5856
13602846565 198 910 1108
13660577991 660 690 1350
13719199419 240 0 240
13726130503 299 681 980
13726238888 2481 24681 27162
13760778710 120 120 240
13822544101 264 0 264
13884138413 4116 1432 5548
13922314466 3008 3720 6728
13925057413 11058 4243 15301
13926251106 240 0 240
13926435656 132 1512 1644
15013685858 369 338 707
15889002119 938 380 1318
15920133257 316 296 612
18212575961 1527 2106 3633
18320173382 9531 212 9743

猜你喜欢

转载自www.cnblogs.com/hidamowang/p/10802505.html