学习大数据接触到的第一个编程思想 MapReduce。

 

前言

之前在学习大数据的时候,很多东西很零散的做了一些笔记,但是都没有好好去整理它们,这篇文章也是对之前的笔记的整理,或者叫输出吧。一来是加深自己的理解,二来是希望这些东西能帮助想要学习大数据或者说正在学习大数据的朋友。如果你看到里面的东西,让你知道了它,这也是一种进步嘛。说不定就开启了你的另一扇大门呢?

 

先来看一个问题

在讲 MapReduce 之前,我们先来看一个问题。我们都知道,在大数据场景中,最先让人了解到的就是数据量大。当数据量大了以后,我们在处理一些问题的时候,可能就没办法按照以前我们传统的方式去解决问题。

我们以一个简单的单词计数来看这个问题。

比如现在我们有一个文件,就10M,里面存放的是一篇英文文档,我们现在的需求就是计算单词出现的次数。

按照我们以前写 Java 代码的套路来做,大概就是读取文件,把数据加载到内存,然后new 一个map来存最后的结果。key 就是单词,value 就是单词出现的次数。

 然后从文件中读取一行数据,然后对这行数据按空格进行切割,然后对切割后的一个一个的单词进行处理,看map 中是否存在,存在就 value + 1,不存在就设置 value 为 1 。

 然后再读取一行数据重复上面的操作,直到结束。很简单吧。

是的,没问题,刚才文件是 10M,处理完成秒秒钟的事情,但是现在我的文件是 2T 的大小,看清楚呃,是两个 T 的文件需要处理,那你现在要怎么做?还去加载到内存么?

想想你公司的机器配置,内存多大,8G,16G,32G ...,顶起天 128G 吧。先不说多大,再想想现在内存价格是多少,128G 的内存得花多少钱。很显然,现在这么玩儿,玩不了吧。

但是,现在一般你公司的机器都还是有不少台吧。那么如果说我们现在把这些机器组成一个 N 节点的集群,然后把这 2T 的文件切分成很多个小文件,然后丢到这些机器上面去计算执行统计,最后再进行一个汇总,是不是就解决了上面的内存不足的问题。

 

MapReduce 思想

MapReduce 是一种编程模型,用于大规模数据集(大于1TB)的并行运算,源于 Google 一篇论文,它充分借鉴了 “分而治之” 的思想,将一个数据处理过程拆分为主要的Map(映射)与Reduce(化简)两步。

对比上面的例子来说,Map 阶段就是每个机器处理切好的数据片的阶段,Reduce 阶段则是最后统计汇总的阶段。

那么,针对前面说的例子大概可以用下面这个图来描述它:

 

简单说一下上面的思路:

第一步:把两个T 的文件分成若干个文件块(block)分散存在整个集群上,比如128M 一个。

第二步:在每台机器上运行一个map task 任务,分别对自己机器上的文件进行统计:

1.先把数据加载进内存,然后一行一行的对数据进行读取,按照空格来进行切割。

2.用一个 HashMap 来存储数据,内容为 <单词,数量>

3.当自己本地的数据处理完成以后,将数据进行输出准备

4.输出数据之前,先把HashMap 按照首字母范围分成 3 个HashMap5.将3个 HashMap 分别发送给 3个 Reduce task 进行处理,分发的时候,同一段单词的数据,就会进入同一个 Reduce task 进行处理,保证数据统计的完整性。

第三步: Reduce task 把收到的数据进行汇总,然后输出到 hdfs 文件系统进程存储。

上面的过程可能遇到的问题

上面我们只是关心了我们业务逻辑的实现,其实系统一旦做成分布式以后,会面临非常多的复杂问题,比如:

•你的 Map task 如何进行任务分配?

•你的 Reduce task 如何分配要处理的数据任务?

•Map task 和 Reduce task 之间如何进行衔接,什么时候去启动Reduce Task 呀?

•如果 Map task 运行失败了,怎么处理?

•Map task 还要去维护自己要发送的数据分区,是不是也太麻烦了。

•等等等等等

 

为什么要用 MapReduce

可见在程序由单机版扩成分布式时,会引入大量的复杂工作。为了提高开发效率,可以将分布式程序中的公共功能封装成框架,让开发人员可以将精力集中于业务逻辑。

而 MapReduce 就是这样一个分布式程序的通用框架。

 

WordCount 示例

用一个代码示例来演示,它需要3个东西,一个是map task ,一个是 reduce task ,还有就是启动类,不然怎么关联他们的关系呢。

首先是 map task :

package com.zhouq.mr;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Mapper;import java.io.IOException;/** * KEYIN 默认情况下,是MR 框架中读取到的一行文本的起始偏移量,long 类型 * 在hadoop 中有自己更精简的序列化接口,我们不直接用Long ,而是用 LongWritable * VALUEIN : 默认情况下,是MR 中读取到的一行文本内容,String ,也有自己的类型 Text 类型 * <p> * KEYOUT : 是用户自定义的逻辑处理完成后的自定义输出数据的key ,我们这里是单词,类型为string 同上,Text * <p> * VALUEOUT: 是用户自定义的逻辑处理完成后的自定义输出value 类型,我们这里是单词数量Integer,同上,Integer 也有自己的类型 IntWritable * <p> */public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {    /**     * map 阶段的业务逻辑就写在map 方法内     * maptask 会对每一行输入数据 就调用一次我们自定义的map 方法。     */    @Override    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {        //拿到输入的这行数据        String line = value.toString();        //根据空格进行分割得到这行的单词        String[] words = line.split(" ");        //将单词输出为 <word,1>        for (String word : words) {            //将单词作为key ,将次数 做为value输出,            // 这样也利于后面的数据分发,可以根据单词进行分发,            // 以便于相同的单词落到相同的reduce task 上,方便统计            context.write(new Text(word), new IntWritable(1));        }    }}

接下来是 reduce task 逻辑:

/** * KEYIN VALUEIN 对于map 阶段输出的KEYOUT VALUEOUT * <p> * KEYOUT :是自定义 reduce 逻辑处理结果的key * VALUEOUT : 是自定义reduce 逻辑处理结果的 value */public class WordcountReduce extends Reducer<Text, IntWritable, Text, IntWritable> {    /**     * <zhouq,1>,<zhouq,1>,<zhouq,2> ......     * 入参key 是一组单词的kv对 的 key     */    @Override    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {        //拿到当前传送进来的 单词//        String word = key.toString();        //        int count = 0;        for (IntWritable value : values) {            count += value.get();        }        //这里的key  就是单词        context.write(key, new IntWritable(count));    }}

 

最后是启动类:

 

/** * wc 启动类 */public class WordCountDriver {    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {        Configuration conf = new Configuration();        // mapreduce.framework.name 配置成 local 就是本地运行模式,默认就是local        // 所谓的集群运行模式 yarn ,就是提交程序到yarn 上. 要想集群运行必须指定下面三个配置.//        conf.set("mapreduce.framework.name", "yarn");//        conf.set("yarn.resoucemanager.hostname", "mini1");        //conf.set("fs.defaultFS","com.zhouq.hdfs://mini1:9000/");        Job job = Job.getInstance(conf);        //指定本程序的jar 包 所在的本地路径        job.setJarByClass(WordCountDriver.class);        //指定本次业务的mepper 和 reduce 业务类        job.setMapperClass(WordCountMapper.class);        job.setReducerClass(WordcountReduce.class);        //指定mapper 输出的 key  value 类型        job.setMapOutputKeyClass(Text.class);        job.setMapOutputValueClass(IntWritable.class);        //指定 最终输出的 kv  类型        job.setOutputKeyClass(Text.class);        job.setOutputValueClass(IntWritable.class);        //指定job的输入原始文件所在目录        FileInputFormat.setInputPaths(job,new Path(args[0]));        //指定job 输出的文件目录        FileOutputFormat.setOutputPath(job,new Path(args[1]));        boolean waitForCompletion = job.waitForCompletion(true);        System.exit(waitForCompletion ? 0 : 1);    }}

 

配置启动类参数:填写输入目录和输出目录,注意输出目录不能存在,不然会执行失败的。

 

执行我们就用编辑器执行,用本地模式,不提交到hadoop 集群上,执行完成后,去到输出目录下可以看到这些文件: 

 

然后输出一下 part-r-00000 这个文件:

代码地址:https://github.com/heyxyw/bigdata/blob/master/bigdatastudy/mapreduce/src/main/java/com/zhouq/mr/WordCountDriver.java

 

最后

希望对你有帮助。后面将会去讲 MapReduce 是如何去运行的。

 

作者·往期内容:

记一次阿里巴巴一面的经历

 


作者介绍:乔二爷,在成都乔二爷这个名字是之前身边的同事给取的,也不知道为啥。也习惯了他们这样叫我。

一直待在相对传统一点的企业,有四年半的 Java 开发经验,会点大数据的内容,也跟客户打过一年的交道,还带过 10个月 10人+的技术团队,有一定的协调组织能力,能够理解 boss 的工作内容,也能很好的配合别人做事。


Java 极客技术公众号,是由一群热爱 Java 开发的技术人组建成立,专注分享原创、高质量的 Java 文章。如果您觉得我们的文章还不错,请帮忙赞赏、在看、转发支持,鼓励我们分享出更好的文章。

关注公众号,大家可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料。

MapReduce 编程模型 & WordCount 示例的更多相关文章

  1. MapReduce编程模型简介和总结

    MapReduce应用广泛的原因之一就是其易用性,提供了一个高度抽象化而变得非常简单的编程模型,它是在总结大量应用的共同特点的基础上抽象出来的分布式计算框架,在其编程模型中,任务可以被分解成相互独立的 ...

  2. MapReduce编程模型详解(基于Windows平台Eclipse)

    本文基于Windows平台Eclipse,以使用MapReduce编程模型统计文本文件中相同单词的个数来详述了整个编程流程及需要注意的地方.不当之处还请留言指出. 前期准备 hadoop集群的搭建 编 ...

  3. 批处理引擎MapReduce编程模型

    批处理引擎MapReduce编程模型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. MapReduce是一个经典的分布式批处理计算引擎,被广泛应用于搜索引擎索引构建,大规模数据处理 ...

  4. mapreduce编程模型你知道多少?

    上次新霸哥给大家介绍了一些hadoop的相关知识,发现大家对hadoop有了一定的了解,但是还有很多的朋友对mapreduce很模糊,下面新霸哥将带你共同学习mapreduce编程模型. mapred ...

  5. MapReduce 编程模型

    一.简单介绍 1.MapReduce 应用广泛的原因之中的一个在于它的易用性.它提供了一个因高度抽象化而变得异常简单的编程模型. 2.从MapReduce 自身的命名特点能够看出,MapReduce ...

  6. [转]Hadoop集群_WordCount运行详解--MapReduce编程模型

    Hadoop集群_WordCount运行详解--MapReduce编程模型 下面这篇文章写得非常好,有利于初学mapreduce的入门 http://www.nosqldb.cn/1369099810 ...

  7. MapReduce 编程模型概述

    MapReduce 编程模型给出了其分布式编程方法,共分 5 个步骤:1) 迭代(iteration).遍历输入数据, 并将之解析成 key/value 对.2) 将输入 key/value 对映射( ...

  8. MapReduce编程模型及其在Hadoop上的实现

    转自:https://www.zybuluo.com/frank-shaw/note/206604 MapReduce基本过程 关于MapReduce中数据流的传输过程,下图是一个经典演示:  关于上 ...

  9. 【MapReduce】二、MapReduce编程模型

      通过前面的实例,可以基本了解MapReduce对于少量输入数据是如何工作的,但是MapReduce主要用于面向大规模数据集的并行计算.所以,还需要重点了解MapReduce的并行编程模型和运行机制 ...

随机推荐

  1. Spark学习之路(十四)—— Spark Streaming 基本操作

    一.案例引入 这里先引入一个基本的案例来演示流的创建:获取指定端口上的数据并进行词频统计.项目依赖和代码实现如下: <dependency> <groupId>org.apac ...

  2. spring 5.x 系列第7篇 —— 整合Redis客户端 Jedis和Redisson (xml配置方式)

    文章目录 一.说明 1.1 Redis 客户端说明 1.2 Redis可视化软件 1.3 项目结构说明 1.3 依赖说明 二.spring 整合 jedis 2.1 新建基本配置文件 2.2 单机配置 ...

  3. 第一章 corejava的入门

    第一章 corejava的入门一:什么是语言语言=os+数据结构+算法+思想os:操作系统数据结构:队,栈,二叉树,链表算法:做游戏开发时非常重要面试题:int a>0,b>0只使用一条输 ...

  4. laravel配置不同环境的配置文件

    //在入口bootstrap/App.php中 $env = $app->detectEnvironment( function () use ($app) { $uname = php_una ...

  5. GitLab通过API创建项目

    示例: #!/usr/bin/python # -*- coding:utf-8 -*- import os import json import requests import subprocess ...

  6. centOS7.3 6忘记密码/修改root密码

    RedHat最近升级了centos linux操作系统,更新为centos7,更新幅度之大,连红帽官方的认证RHCE也进行了升级,认证必须使用rhel7,可见红帽官方对centos7的重视程度. 最新 ...

  7. c#基础二

    对VS2012的理解 1.导入命名空间 命名空间就是类的"文件夹".类就是"文件夹"中的文件.需要导入命名空间 添加引用: 如果我需要在一个项目中,访问另一个项 ...

  8. 记一次linux通过jstack定位CPU使用过高问题或排查线上死锁问题

    一.java定位进程 在服务器中终端输入命令:top 可以看到进程ID,为5421的cpu这列100多了. 记下这个数字:5421 二.定位问题进程对应的线程 然后在服务器中终端输入命令:top -H ...

  9. c++ 队列的基本应用

    c++ 队列的基本应用 题目描述 现在去营业厅办理业务,都要先取号,再等待叫号.叫号系统有两种模式: 1.取号,取号时要输入自己的11位电话号码,号码按取号的顺序存在系统中: 2.叫号,叫号时会显示当 ...

  10. Event StoryLine Corpus 论文阅读

    Event StoryLine Corpus 论文阅读 本文是对 Caselli T, Vossen P. The event storyline corpus: A new benchmark fo ...