十、Hadoop的序列化

       上篇博客介绍了Hadoop核心组件之MapReduce,本篇主要介绍Hadoop的序列化,关注专栏《破茧成蝶——Hadoop篇》查看相关系列的文章~


目录

一、序列化概述

二、序列化实例

2.1 数据与需求

2.2 编写Bean对象

2.3 编写Mapper类

2.4 编写Reducer类

2.5 编写Driver类

2.6 测试


一、序列化概述

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

       Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化之后,会附带很多额外的信息,例如:各种校验信息、Header等。不便于在网络中高效传输。所以Hadoop自己开发了一套序列化机制(Writable)。Hadoop序列化的特点:(1)可以高效的使用存储空间。(2)读写数据的额外开销小。(3)随着通信协议的升级而可升级。(4)支持多语言的交互。

二、序列化实例

2.1 数据与需求

       首先先来看看数据吧,先分析下数据:

       这是一段经过处理的Nginx后台日志信息,字段依次是:时间、版本、客户端ip、访问路径、状态、域名、服务端ip、size、响应时间。现在我们统计一下每一个客户端ip对应的总size,文件名称为nginx_log。

2.2 编写Bean对象

package com.xzw.hadoop.mapreduce.nginx;

import org.apache.hadoop.io.Writable;

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

/**
 * @author: xzw
 * @create_date: 2020/7/28 10:01
 * @desc:
 * @modifier:
 * @modified_date:
 * @desc:
 */
public class NginxBean implements Writable {//实现Writable接口
    private long size;//size

    //反序列化时,需要反射调用空参构造器,所以必须有空参构造器
    public NginxBean() {
    }

    public void set(long size) {
        this.size = size;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    /**
     * 序列化方法
     * @param dataOutput
     * @throws IOException
     */
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeLong(size);
    }

    /**
     * 反序列化方法:反序列化方法读取顺序必须跟序列化方法写顺序一致
     * @param dataInput
     * @throws IOException
     */
    public void readFields(DataInput dataInput) throws IOException {
        this.size = dataInput.readLong();
    }

    /**
     * 编写toString方法,方便后续打印到文本
     * @return
     */
    @Override
    public String toString() {
        return size + "\t";
    }
}

2.3 编写Mapper类

package com.xzw.hadoop.mapreduce.nginx;

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

import java.io.IOException;

/**
 * @author: xzw
 * @create_date: 2020/7/28 10:30
 * @desc:
 * @modifier:
 * @modified_date:
 * @desc:
 */
public class NginxMapper extends Mapper<LongWritable, Text, Text, NginxBean> {
    NginxBean nginxBean = new NginxBean();
    Text text = new Text();

    @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 clientIP = fields[2];//取出客户端的IP
        long size = Long.parseLong(fields[fields.length - 2]);//取出size

        text.set(clientIP);
        nginxBean.set(size);

        //4、写出
        context.write(text, nginxBean);
    }
}

2.4 编写Reducer类

package com.xzw.hadoop.mapreduce.nginx;

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

import java.io.IOException;

/**
 * @author: xzw
 * @create_date: 2020/7/28 10:39
 * @desc:
 * @modifier:
 * @modified_date:
 * @desc:
 */
public class NginxReducer extends Reducer<Text, NginxBean, Text, NginxBean> {
    private NginxBean nginxBean = new NginxBean();

    @Override
    protected void reduce(Text key, Iterable<NginxBean> values, Context context) throws IOException, InterruptedException {
        long sum_size = 0;

        //1、遍历所有的数据,将需要的数据进行累加
        for (NginxBean nginxBean: values) {
            sum_size += nginxBean.getSize();
        }

        //2、封装对象
        nginxBean.set(sum_size);

        //3、写出
        context.write(key, nginxBean);
    }
}

2.5 编写Driver类

package com.xzw.hadoop.mapreduce.nginx;

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;

/**
 * @author: xzw
 * @create_date: 2020/7/28 10:48
 * @desc:
 * @modifier:
 * @modified_date:
 * @desc:
 */
public class NginxDriver {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        //输入输出路径
        args = new String[]{"e:/input/nginx_log", "e:/output"};

        //1、获取配置信息或者job实例
        Job job = Job.getInstance(new Configuration());

        //2、设置类路径
        job.setJarByClass(NginxDriver.class);

        //3、设置Mapper和Reducer
        job.setMapperClass(NginxMapper.class);
        job.setReducerClass(NginxReducer.class);

        //4、设置Mapper和Reducer的输出类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(NginxBean.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NginxBean.class);

        //5、设置输入输出的数据
        FileInputFormat.setInputPaths(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        //6、提交job
        boolean b = job.waitForCompletion(true);
        System.exit(b ? 0 : 1);
    }
}

2.6 测试

       运行Driver,得到测试结果:

       当然,也可以提交到集群中,具体打包方法在这就不再赘述了,可以参考上篇博客《九、Hadoop核心组件之MapReduce》中的打包运行方式。

       至此,本文就讲解完了,你们在这个过程中遇到了什么问题,欢迎留言,让我看看你们遇到了什么问题~

猜你喜欢

转载自blog.csdn.net/gdkyxy2013/article/details/107613044