Hadoop序列化

序列化概述

(1) 什么是序列化

      序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储到磁盘(持久化)和网络传输。 
       反序列化就是将收到字节序列(或其他数据传输协议)或者是磁盘的持久化数据,转换成内存中的对象。

(2)为什么要序列化

一般来说,“活的”对象只生存在内存里,关机断电就没有了。而且“活的”对象只能由本地的进程使用,不能被发送到网络上的另外一台计算机j。 然而序列化可以存储“活的”对象,可以将“活的”对象发送到远程计算机。

(3)为什么不用java的序列化

java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,Header,继承体系等),不便于在网络中高效传输。所以,Hadoop自己开发了一套序列化机制(Writable)。

(4)Hadoop序列化特点

紧凑 :高效使用存储空间。
快速:读写数据的额外开销小。
互操作:支持多语言的交互

在Hadoop中提供了序列化类型

 

自定义序列化

 但是只有这些还是远远不够的,我们在开发中经常需要自定义对象也能序列化

 自定义对象实现序列化需要实现序列化接口 Writable

步骤分为7步

(1)必须实现Writable接口

(2)反序列化时,需要反射调用空参构造函数,所以必须有空参构造

public FlowBean() {
	super();
}

(3) 重写序列化方法

@Override
public void write(DataOutput out) throws IOException {
	out.writeLong(upFlow);
	out.writeLong(downFlow);
	out.writeLong(sumFlow);
}

(4)重写反序列方法

@Override
public void readFields(DataInput in) throws IOException {
	upFlow = in.readLong();
	downFlow = in.readLong();
	sumFlow = in.readLong();
}

(5)注意序列化 和反序列化的顺序要一致

(6)要想把结果显示在文件中,需要重写toString() 方法。可以用“\t”分开,方便后续使用

(7)如果需要将自定义的bean放在key中传输,还需要实现Comparable接口,因为MapReduce框架中Shuff过程要求对Key能排序。

@Override
public int compareTo(FlowBean o) {
	// 倒序排列,从大到小
	return this.sumFlow > o.getSumFlow() ? -1 : 1;
}

序列化案例实操

 (2)需求分析

3  编写MapReduce

(1) 编写 流量统计的Bean类

package com.chenxiang.mapreduce.writable;

import org.apache.hadoop.io.Writable;

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

/*
 *
 * 1 定义类实现writable接口
 * 2 重写序列化和反序列化方法
 * 3  空参构造方法
 * 4 toString 方法*/
public class FlowBean implements Writable {
    private long upFlow;//上行流量
    private long downFlow;//下行流量
    private long sumFlow;//总流量
    //空参构造

    public long getUpFlow() {
        return upFlow;
    }

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

    public long getDownFlow() {
        return downFlow;
    }

    public void setDownFlow(long downFlow) {
        this.downFlow=downFlow;

    }

    public long getSumFlow() {
        return sumFlow;
    }

    public void setSumFlow() {
         this.sumFlow= this.upFlow+this.downFlow;
    }

    public FlowBean() {
    }

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeLong(upFlow);
        out.writeLong(downFlow);
        out.writeLong(sumFlow);


    }

    @Override
    public void readFields(DataInput in) throws IOException {

       this.upFlow= in.readLong();
       this.downFlow=in.readLong();
       this.sumFlow=in.readLong();

    }

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

(2)编写Mapper类

package com.chenxiang.mapreduce.writable;

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

import java.io.IOException;


public class FlowMapper extends Mapper<LongWritable, Text, Text, FlowBean> {

    private Text outK = new Text();
    private FlowBean outV = new FlowBean();

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // //获取一行信息
        String line = value.toString();

        String[] split = line.split("\t");//切割

        // 抓取数据

        String phone = split[1];
        String up = split[split.length - 3];
        String down = split[split.length - 2];

        //封装
            outK.set(phone);
            outV.setUpFlow(Long.parseLong(up));
            outV.setDownFlow(Long.parseLong(down));
            outV.setSumFlow();

            // 写出
        context.write(outK,outV);


    }
}

(3)编写Reducer类

package com.chenxiang.mapreduce.writable;

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

import java.io.IOException;

public class FlowReducer extends Reducer<Text,FlowBean, Text,FlowBean> {

    private  FlowBean outV =new FlowBean();
    @Override
    protected void reduce(Text key, Iterable<FlowBean> values, Context context) throws IOException, InterruptedException {


        //遍历累加值
        long totalUp=0;
        long totalDown=0;
        for(FlowBean value:values)
        {
            totalUp+=value.getUpFlow();
            totalDown+=value.getDownFlow();

        }
        //2 封装
        outV.setDownFlow(totalDown);
        outV.setUpFlow(totalUp);
        outV.setSumFlow();
        context.write(key,outV);

    }
}

(4)编写Driver驱动类

package com.chenxiang.mapreduce.writable;


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;

import java.io.IOException;

public class FlowDriver {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

        // 1 获取job
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        //2 设置jar
        job.setJarByClass(FlowDriver.class);
        //3 关联 mapper reducer

        job.setMapperClass(FlowMapper.class);
        job.setReducerClass(FlowReducer.class);

        // 4 设置Mapper输出类型
        job.setMapOutputValueClass(FlowBean.class);
        job.setMapOutputKeyClass(Text.class);
        //设置Mapper最终输出路径
        job.setOutputValueClass(FlowBean.class);
        job.setOutputKeyClass(Text.class);
        //6 设置数据的输入路径和输出路径
        FileInputFormat.setInputPaths(job, new Path("D:\\input\\inputflow"));
        FileOutputFormat.setOutputPath(job, new Path("D:\\output\\output8"));

        //7 提交job

        boolean result = job.waitForCompletion(true);

        System.exit(result ? 0 : 1);


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值