总访问量: PV

DataScience && DataMining && BigData

Hadoop序列化

  数据在虚拟机内外交换的方式简称为序列化

    *序列化(Serialization)是指把结构化对象转化为字节流。(写出去,以内存中得对象为基础或参照物)

    *反序列化(Deserialization)是序列化的逆过程。即把字节流转回结构化对象。(读进来,以内存中得对象为基础或参照物)

    Java序列化(java.io.Serializable),接口,只需要实现该接口即可,Serializable已经提供了java序列化的实现

1.hadoop序列化源碼

    在hadoop中,可以使用ctrl+shift+t打开open type,键入hadoop序列化的类型writable即可查看

    

            

          注意:这里的序列化方法需要自己在程序中实现,而java提供了默认的实现。

                 

(2)LongWritable类源码

      

    

    crtl+鼠标点击WritableComparable可看到,这个接口最终集成了Writable和Comparable两个接口

     

    (3)同理:可以查看Text的源码,如下

     

    

(4)序列化对应:

    

       注:VlongWritable是变长类型

        

6.总结:

            

由于java或hadoop本身的类型有限,更多的是自定义的类型,因此自定义类型是更加重要的类型

    7. 项目:电信中得手机上网流量的统计(业务中将上行包数+下行包数+上行总流量+下行总流量四个字段进行相加即为流量汇总)

          

 

   但是,上述四个字段并没有统一的单位,是不能相加的,因此只能一列所有的值进行相加,也就得到的是上行数据包总数,下行数据包总数,下行流量总数和上行流量总数等信息。

   Mapreduce实现:

       <k1,v1>中k1 是每一行起始位置,v1是每一行内容,k1在代码中没有用到(map的输入)

       最终结果<k3,v3>得到的是<手机号码k3,上行数据包总数,下行数据包总数,下行流量总数,上行流量总数v3>

       难点:如何算k3,v3(reducer的输出)?

                而<k2,v2>确定其含义是至关重要的,原理是根据分组是按照k2分组的,

分组是让相同key的value放在一起,也就是相同key的value相加即为流量数据。

                因此,k2为手机号码,v2就是上述4个流量。

       解决:Longwritable等只能处理一个数据,而现在要处理四个数据,这时候需要自己自定义这种类型。

      t1,t2,t3,t4分别为上行数据包总数,下行数据包总数,下行流量总数,上行流量总数。

              下面程序为自定义类型的代码:

	private static class TrafficWritable implements Writable{
		public long t1;
		public long t2;
		public long t3;
		public long t4;
		public void write(DataOutput out) throws IOException {
			out.writeLong(t1);
			out.writeLong(t2);
			out.writeLong(t3);
			out.writeLong(t4);
		}

		public void readFields(DataInput in) throws IOException {
			//顺序不可颠倒,和写出去的顺序需要一致
			this.t1=in.readLong();
			this.t2=in.readLong();
			this.t3=in.readLong();
			this.t4=in.readLong();
		}
		@Override
		public String toString() {
			return Long.toString(t1)+"\t"+Long.toString(t2)+"\t"+Long.toString(t3)+"\t"+Long.toString(t4);
		}
	}

  业务实现的Hadoop代码如下:

package Mapreduce;

import java.io.DataInput;
import java.io.DataOutput;
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.io.Writable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class Traffic {
	public static void main(String[] args) throws Exception {
		Job job = Job.getInstance(new Configuration(), Traffic.class.getSimpleName());
		job.setJarByClass(Traffic.class);
		//1.自定义输入路径
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		//2.自定义mapper
		//job.setInputFormatClass(TextInputFormat.class);
		job.setMapperClass(MyMapper.class);
		//job.setMapOutputKeyClass(Text.class);
		//job.setMapOutputValueClass(TrafficWritable.class);
		
		//3.自定义reduce
		job.setReducerClass(MyReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(TrafficWritable.class);
		//4.自定义输出路径
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		//job.setOutputFormatClass(TextOutputFormat.class);//对输出的数据格式化并写入磁盘
		
		job.waitForCompletion(true);
		
	}
	private static class MyMapper extends Mapper<LongWritable, Text, Text, TrafficWritable>{
		Text k2 =new Text(); //k2为第二个字段,手机号码
		TrafficWritable v2 = new TrafficWritable();
		@Override
		protected void map(
				LongWritable key,
				Text value,
				Mapper<LongWritable, Text, Text, TrafficWritable>.Context context)
				throws IOException, InterruptedException {
			// TODO Auto-generated method stub
			String line = value.toString();
			String[] splited = line.split("\t");
			//手机号码,第二个字段为手机号
			k2.set(splited[1]);
			//流量,注:写代码的时候先写方法名在写方法的实现(测试驱动开发s)
			v2.set(splited[6],splited[7],splited[8],splited[9]);
			context.write(k2, v2);
		}
	}
	private static class MyReducer extends Reducer<Text, TrafficWritable, Text, TrafficWritable>{
		TrafficWritable v3 = new TrafficWritable();
		@Override
		protected void reduce(
				Text k2, //表示手机号码
				Iterable<TrafficWritable> v2s,  //相同手机号码流量之和
				Reducer<Text, TrafficWritable, Text, TrafficWritable>.Context context)
				throws IOException, InterruptedException {
			//迭代v2s,将里面的植相加即可
			long t1 =0L;
			long t2 =0L;
			long t3 =0L;
			long t4 =0L;
			for (TrafficWritable v2 : v2s) {
				t1+=v2.t1;
				t2+=v2.t2;
				t3+=v2.t3;
				t4+=v2.t4;
			}
			v3.set(t1, t2, t3, t4);
			context.write(k2, v3);//如果执行没有输出的话,可能reduce没有往外写,或mapper没有写,或源文件没有数据
		}
	}
	//自定义类型
	private static class TrafficWritable implements Writable{
		public long t1;
		public long t2;
		public long t3;
		public long t4;
		public void write(DataOutput out) throws IOException {
			out.writeLong(t1);
			out.writeLong(t2);
			out.writeLong(t3);
			out.writeLong(t4);
		}
		//t1-4原来是TrafficWritable类型,在set中进行转换
		public void set(long t1, long t2, long t3, long t4) {
			// TODO Auto-generated method stub
			this.t1=t1;
			this.t2=t2;
			this.t3=t3;
			this.t4=t4;
		}

		public void set(String t1, String t2, String t3,String t4) {
			// v2的set方法
			this.t1=Long.parseLong(t1);
			this.t2=Long.parseLong(t2);
			this.t3=Long.parseLong(t3);
			this.t4=Long.parseLong(t4);
		}

		public void readFields(DataInput in) throws IOException {
			//顺序不可颠倒,和写出去的顺序需要一致
			this.t1=in.readLong();
			this.t2=in.readLong();
			this.t3=in.readLong();
			this.t4=in.readLong();
		}
		@Override
		public String toString() {
			return Long.toString(t1)+"\t"+Long.toString(t2)+"\t"+Long.toString(t3)+"\t"+Long.toString(t4);
		}
	}
}

  将代码打包并在linux中运行

      (1)将文件HTTP开头的文件和Traffic.jar包上传到linux中

      

      (2)上传HTTP开头的业务文件到HDFS的/data中,并查看此文件信息

      

      (3)执行jar文件

     

    (4)查看输出结果

    

注意:可能遇到的问题

    (1)查看生成的文件,沒有輸出,這時候需要檢查代碼的Reduce端是否寫出來,或map端是否寫出,在或者文件是否爲空

    

    (2)如果在出錯的環境下會產生/out2目錄,此時如果再次運行hadoop代碼會出現文件已經存在的問題,此時采用如下頒發

    

 

 

    END~

    Tip 优化:

      

     解答:如果new对象写在map函数里面,程序不会出现任何问题,但是,当数据行数非常大的话,每一行调用一次map函数,

会new很多对象,JVM也会一直处于高负荷状态,从而使得程序运行效率下降。

 

posted @ 2017-02-15 16:11  CJZhaoSimons  阅读(561)  评论(3编辑  收藏  举报