一小时搞定Mapreduce程序

之前一直用hive处理数据,觉得MR程序打包上传的比较麻烦,后来偶遇hive搞不定的文件网上找了个MR的例子稍微改一下感觉也比较方便,主要是处理速度快。

MR程序主要是有3各类:main函数类,map重载类,reduce重载类。

第一步:maven里面添加几个jar包:

代码如下:

<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>2.7.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-hdfs</artifactId>
        <version>2.7.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-mapreduce-client-core</artifactId>
        <version>2.7.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
        <version>2.7.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-mapreduce-client-common</artifactId>
        <version>2.7.1</version>
    </dependency>

</dependencies>

第二步:main类:主要是调度MR程序的启动运行

代码如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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 org.apache.hadoop.util.GenericOptionsParser;
public class WordCount {
    public static void main(String[]args)throws Exception
    {
        Configuration conf = new Configuration(); //从hadoop配置文件读取参数
        String [] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs(); //从命令行读取参数
        if(otherArgs.length!=2)
        {
            System.err.println("Usage:wordcount<in><out>");
            System.exit(2);
        }
        Job job = new Job(conf,"wordcount");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(TokenizerMapper.class);
        job.setReducerClass(IntSumReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job,new Path(otherArgs[0]));
        FileOutputFormat.setOutputPath(job,new Path(otherArgs[1]));
        System.exit(job.waitForCompletion(true)?0:1);
    }
}

第三步:Map类:主要是按行读取文件内容,根据自己需要处理(默认按回车换行分割,如果要改动需要重载某个函数)

代码如下:

import java.io.IOException;                  //导入异常处理类
import org.apache.hadoop.io.IntWritable;     //导入整数类
import org.apache.hadoop.io.Text;            //导入文本类
import org.apache.hadoop.mapreduce.Mapper;   //导入Mapper类
public class TokenizerMapper extends Mapper<Object,Text,Text,IntWritable>{
    Text word = new Text();                 //定义输出键
    //统计每行数据每个id,aaa字符出现的次数
    public void map(Object key,Text value,Context context)throws IOException,InterruptedException
    {
        int len = 0;
        String id="";
        len = appearNumber(value.toString(),"aaa");    //统计aaa出现次数
        index = value.toString().indexOf("\"id\":\"");
        if(index>0)
        {
            id = value.toString().substring(index+n,index+m); //取每行id值
            IntWritable one = new IntWritable(len);
            Text id_t = new Text(id);
            context.write(id_t,one);
        }
    }
    public static int appearNumber(String srcText, String findText) {
        int count = 0;
        int index = 0;
        while ((index = srcText.indexOf(findText, index)) != -1) {
            index = index + findText.length();
            count++;
        }
        return count;
    }
}

第四步:重载reduce类

  代码如下:

import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable>  {

    IntWritable result = new IntWritable();
    public void reduce(Text key,Iterable<IntWritable> values,Context context)
            throws IOException,InterruptedException
    {
        int sum = 0;
        for(IntWritable val:values) //不断地将values中的IntWritable整数提取出来给val
        {
            sum=sum + val.get();

        }
        result.set(sum);
        context.write(key,result);  //每个id的aaa出现的次数求和输出

    }

}

第五步:打成jar包。上传hadoop,运行

hadoop  jar   mr_test1.jar   WordCount   hdfs:///myfile/test.log    hdfs:///myfile/output10

PS:hdfs:///myfile/2018042319.log  为输入日志文件

         hdfs:///myfile/output10 指定的输出目录

结果文件在:hdfs:///myfile/output10/part-r-00000 

为了验证reduce阶段的作用,我曾把main函数中job.setReducerClass(IntSumReducer.class); 这句代码注掉,跑出的结果为每个id每行aaa出现的次数。将结果文件某个id  grep出来,例如结果有17行,然后对17行的value求和,和加上job.setReducerClass(IntSumReducer.class)这句,这个id的结果完全一致。

MR程序的运行速度对比

MR程序的运行速度感觉比较快,像这个日志文件约10G,一开始的时候出于简单的想法写了一个shell脚本去处理,放在内存192G,CPU64核物理机运行,发现每秒大概只能处理不到1000条数据,算下来跑完需要约10小时,想shell的结果和mr的结果进行对比,所以就没有kill。如果只是慢也就算了,shell脚本执行完几个小时,运维忽然通知这台服务器重启了,也没有太详细的dump信息,说大概是内存不足。。。幸亏只是一台节点机,无其它定时任务,所以对集群无影响。估计是shell管理内存有硬伤,系统本身也有一些内存没来得及释放。

上面的MR程序运行在同样配置的物理机集群,约40台,10G文件运行也就几分钟,对比shell的结果基本相同,感觉速度快了不止一个数量级。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值