MR例子(统计各个手机号在某段时间内产生的总流量)

目的:统计各个手机号在某段时间类产生的总流量

准备文件 (已经上传到hdfs上 文件名data.txt)
这里写图片描述

上图中对应的字段如下图
这里写图片描述


文件及代码分析

所给的文件是每一个用户每一次上网产生的流量,先如今需要将相同用户进行聚合。
最后输出的结果字段:手机号 上行总流量 下行总流量 总流量
map的输入输出都是以key value 形式存在。输入的键值对为K1为整数 value为字符串 , 输出的键值对K2为字符串(手机号),输出相当于上行总流量 ,下行总流量 ,总流量的list。所以我们用一个对象(DataBean)来保存它们。
reduce的输入就是map的输出(经过shuffle处理,这里不做详细说明),reduce输出的形式为key为手机号(字符串),value为对象(DataBean)的结果就是我们最后想要的结果。
map进行的业务处理就是取出目标文件中的四个字段,然后进行拆分
reduce进行的业务处理,主要是对map的输出中的DataBean里面的流量进行求和,最后输出,下面直接上代码。


DataBean

package cn.master1.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;
    }

    @Override
    public String toString() {
        return this.upPayLoad + "/t" + this.downPayLoad + "/t" + this.totalPayLoad;
    }

    public void write(DataOutput out) throws IOException {
        out.writeUTF(telNo);
        out.writeLong(upPayLoad);
        out.writeLong(downPayLoad);
        out.writeLong(totalPayLoad);
    }

    public void readFields(DataInput in) throws IOException {
        this.telNo = in.readUTF();
        this.upPayLoad = in.readLong();
        this.downPayLoad = in.readLong();
        this.totalPayLoad = in.readLong();
    }

    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;
    }
}

package cn.master1.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.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 DataCount {

    public static void main(String[] args) throws Exception {
         Configuration conf = new Configuration();
         Job job = Job.getInstance(conf);

         job.setJarByClass(DataCount.class);

         job.setMapperClass(DCMapper.class);
         /*当k2 v2 和 k3 v3 类型一一对应时,此行和下面一行可以省略。*/
         job.setMapOutputKeyClass(Text.class);
         job.setMapOutputValueClass(DataBean.class);
         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);
    }

    public static class DCMapper extends Mapper<LongWritable, Text, Text, DataBean>{

        @Override
        protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, DataBean>.Context context)
                throws IOException, InterruptedException {
            //接收数据
            String line = value.toString();
            String[] fileds = line.split("/t");
            String telNo = fileds[1];
            long up = Long.parseLong(fileds[8]);
            long down = Long.parseLong(fileds[9]);
            DataBean bean  = new DataBean(telNo, up, down);
            context.write(new Text(telNo), bean);
        }

    }

    public static class DCReducer extends Reducer<Text, DataBean, Text, DataBean>{

        @Override
        protected void reduce(Text key, Iterable<DataBean> v2s, Context context)
                throws IOException, InterruptedException {
            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);
        }
    }
}

jar包

打成jar包(不指定入口程序)命名为examples.jar,放到虚拟机跟目录下,然后执行
hadoop jar /root/examples.jar cn.master1.hadoop.mr.dc.DataCount /data.txt /dataout
cn.master1.hadoop.mr.dc.DataCount指定运行的入口程序 /data.txt 目标文件(存在hdfs上) /dataout输出文件(存放到hdfs上)

最后输出结果如下
这里写图片描述


下面简单说一说MR的执行流程和hadoop的序列化

MR执行流程

MR执行流程

(1).客户端提交一个mr的jar包给RM(resourceManage)(提交方式:hadoop jar ...)
(2).JobClient通过RPC和RM进行通信,返回一个存放jar包的地址(HDFS)和jobId
(3).client将jar包写入到HDFS当中(path = hdfs上的地址 + jobId)
(4).开始提交任务(任务的描述信息,不是jar, 包括jobid,jar存放的位置,配置信息等等)
(5).RM进行初始化任务
(6).读取HDFS上的要处理的文件,开始计算输入分片,每一个分片对应一个NM(nodeManage)
(7).NM通过心跳机制领取任务(任务的描述信息)
(8).下载所需的jar,配置文件等。
(9).NM启动一个java child子进程,用来执行具体的任务(MapperTask或ReducerTask)
(10).将结果写入到HDFS当中。

hadoop序列化

  • 序列化的概念
    序列化(Serialization)是指把结构化对象转化为字节流。
    反序列化(Deserialization)是序列化的逆过程。即把字节流转回结构化对象。
    Java序列化(java.io.Serializable)

hadoop序列化并不是用的java自带的序列化机制,java的序列化机制运用的比较广泛,所以序列化和反序列化时保存的东西过多,效率较低,而hadoop在序列化时,只需要保存数据即可,因为只需要传输数据。hadoop具有特定的序列化机制。

  • 序列化格式特点:
    紧凑:高效使用存储空间。
    快速:读写数据的额外开销小
    可扩展:可透明地读取老格式的数据
    互操作:支持多语言的交互

hadoop的序列化格式Writable
更多详细介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值