MapReduce几个小应用

  上篇文章已经介绍了怎么去写一个简单的MR并且将其跑起来,学习一个东西动手还是很有必要的,接下来我们就举几个小demo来体验一下跑起来的快感。

demo链接请参照附件:http://files.cnblogs.com/files/wangkeustc/demo.tar.gz

排序:

  问题:将sort_input文件夹下的多个文件中的数据按照从小到大排序

  设计思路:shuffle阶段会将发送到reduce的数据自动排序,所以我们这边只要保证在每个partiton中数字都是按照从小到大来的,比如第一个分区时1-20000的整数,第二个分区时20000-40000等。

所以这个问题的解答,我们引入了一个新的概念,定义属于自己的Partition类

  

单表关联:

  问题:请参考join_input中的文件输入格式,也就是根据文件中的child-parent关系,找出存在的grandchild-grandparent关系,比如Tom Jerry   和Jerry Mark  ,那么我们可以得到Mark是Tom的grandparent。

  涉及思路:类似于将这张表中的parent和自身中的child做join,mapper阶段我们可以根据Tom  Jerry的关系输入两个key,分别对应<Tom,1 Jerry>,其中1表示是parent和<Jerry,2 Tom>。在Reducer中我们只要把每个key对应的parent和他的child找出来做个循环就可以得到所有结果了。

上面两个例子,大家可以仔细阅读以下代码,最好也手动敲一遍,仔细琢磨以下,因为接下来讲到的MapReduce的工作机制会与此相关。

MapReduce工作机制

MapReduce执行总流程

JobTracker:初始化作业,分配作业,与TaskManager通信,协调整个作业的执行

TaskTracker:保持与JobTracker的通信,执行map或者reduce任务

HDFS:保存作业的数据,配置信息等,保存作业结果。

具体相关流程

提交作业

  客户端编写完程序代码后,打成jar,然后通过相关命令向集群提交自己想要跑的mr任务,具体过程如下:

  1. 通过调用JobTracker的getNewJobId()获取当前作业id
  2. 检查作业相关路径
  3. 计算作业的输入划分,并将划分信息写到Job.split文件中
  4. 将运行作业所需要的资源包括作业jar包,配置文件和甲酸所得的输入划分,复制到作业对应的HDFS上
  5. 调用JobTracker的summitJob()提交,告诉JobTracker作业准备执行

初始化作业

  1. 从HDFS中读取作业对应的job.split,得到输入数据的划分信息
  2. 创建并且初始化Map任务和Reduce任务:为每个map/reduce task生成一个TaskInProgress去监控和调度该task。
     /**
    * Construct the splits, etc. This is invoked from an async
    * thread so that split-computation doesn't block anyone.
    */
    public synchronized void initTasks()
    throws IOException, KillInterruptedException, UnknownHostException {
    if (tasksInited || isComplete()) {
    return;
    }
    ...... jobtracker.getInstrumentation().addWaitingMaps(getJobID(), numMapTasks);
    jobtracker.getInstrumentation().addWaitingReduces(getJobID(), numReduceTasks);
    this.queueMetrics.addWaitingMaps(getJobID(), numMapTasks);
    this.queueMetrics.addWaitingReduces(getJobID(), numReduceTasks); //根据numMapTasks任务数,创建MapTask的总数
    maps = new TaskInProgress[numMapTasks];
    for(int i=0; i < numMapTasks; ++i) {
    inputLength += splits[i].getInputDataLength();
    maps[i] = new TaskInProgress(jobId, jobFile,
    splits[i],
    jobtracker, conf, this, i, numSlotsPerMap);
    }
    ...... //
    // Create reduce tasks
    //根据numReduceTasks,创建Reduce的Task数量
    this.reduces = new TaskInProgress[numReduceTasks];
    for (int i = 0; i < numReduceTasks; i++) {
    reduces[i] = new TaskInProgress(jobId, jobFile,
    numMapTasks, i,
    jobtracker, conf, this, numSlotsPerReduce);
    nonRunningReduces.add(reduces[i]);
    } ...... // create cleanup two cleanup tips, one map and one reduce.
    //创建2个clean up Task任务,1个是Map Clean-Up Task,一个是Reduce Clean-Up Task
    cleanup = new TaskInProgress[2]; // cleanup map tip. This map doesn't use any splits. Just assign an empty
    // split.
    TaskSplitMetaInfo emptySplit = JobSplit.EMPTY_TASK_SPLIT;
    cleanup[0] = new TaskInProgress(jobId, jobFile, emptySplit,
    jobtracker, conf, this, numMapTasks, 1);
    cleanup[0].setJobCleanupTask(); // cleanup reduce tip.
    cleanup[1] = new TaskInProgress(jobId, jobFile, numMapTasks,
    numReduceTasks, jobtracker, conf, this, 1);
    cleanup[1].setJobCleanupTask(); // create two setup tips, one map and one reduce.
    //原理同上
    setup = new TaskInProgress[2]; // setup map tip. This map doesn't use any split. Just assign an empty
    // split.
    setup[0] = new TaskInProgress(jobId, jobFile, emptySplit,
    jobtracker, conf, this, numMapTasks + 1, 1);
    setup[0].setJobSetupTask(); // setup reduce tip.
    setup[1] = new TaskInProgress(jobId, jobFile, numMapTasks,
    numReduceTasks + 1, jobtracker, conf, this, 1);
    setup[1].setJobSetupTask(); ......
  3. 上面的代码块提到的,创建两个初始化task,一个初始化Map,一个初始化Reduce

分配任务

  JobTracker会将任务分配到TaskTracker去执行,但是怎么判断哪些TaskTracker,怎么分配任务呢?所以,我们要实现JobTracker和TaskTracker中的通信,也就是TaskTracker循环向JobTracker发送心跳,向上级报告自己这边是不是还活着,活干的怎么样了,可以接些新活等。作为JobTracker,接收到心跳信息,如果有待分配任务,就会给这个TaskTracker分配一个任务,然后taskTracker就把这个任务加入到他的任务队列中。我们可以主要看看TaskTracker中的transmitHeartBeart()和JobTracker的heartbeat()方法。

执行任务

  TaskTracker申请到任务后,在本地执行,主要有以下几个步骤来完成本地的步骤化:

  1. 将job.split复制到本地
  2. 将job.jar复制到本地
  3. 将job的配置信息写入到Job.xml
  4. 创建本地任务目录,解压job.rar
  5. 调用launchTaskForJob()方法发布任务

  发布任务后,TaskRunner会启动新的java虚拟机来运行每个任务,以map任务为例,流程如下:

  1. 配置任务执行参数(获取java程序的执行环境和配置参数等)
  2. 在child临时文件表中添加Map任务信息
  3. 配置log文件夹,配置Map任务的执行环境和配置参数;
  4. 根据input split,生成RecordReader读取数据
  5. 为Map任务生成MapRunnable,一次从RecordReader中接收数据,并调用map函数进行处理
  6. 将Map函数的输出调用collect收集到MapOUtputBuffer中

Hadoop入门第三篇-MapReduce试手以及MR工作机制的更多相关文章

  1. JavaMail入门第三篇 发送邮件

    JavaMail API中定义了一个java.mail.Transport类,它专门用于执行邮件发送任务,这个类的实例对象封装了某种邮件发送协议的底层实施细节,应用程序调用这个类中的方法就可以把Mes ...

  2. Hadoop入门第四篇:手动搭建自己的hadoop小集群

    前言 好几天没有更新了,本来是应该先写HDFS的相关内容,但是考虑到HDFS是我们后面所有学习的基础,而我只是简单的了解了一下而已,后面准备好好整理HDFS再写这块.所以大家在阅读这篇文章之前,请先了 ...

  3. # hadoop入门第六篇:Hive实例

    前言   前面已经讲了如何部署在hadoop集群上部署hive,现在我们就做一个很小的实例去熟悉HIVE QL.使用的数据是视频播放数据包括视频编码,播放设备编码,用户账号编码等,我们在这个数据基础上 ...

  4. Hadoop入门第五篇:Hive简介以及部署

    标签(空格分隔): Hadoop Hive hwi 1.Hive简介   之前我一直在Maxcompute上进行大数据开发,所以对数仓这块还算比较了解,在接受Hive的时候基本上没什么大的障碍.所以, ...

  5. Html/Css(新手入门第三篇)

    一.学习心得---参考优秀的网页来学习. 1我们只做的静态网页主要用的技术?html+css 只要网上看到的,他的源代码公开的.[1].先去分析,他们页面是如何布局(结构化)[2].再试着去做一下,- ...

  6. Android JNI入门第三篇——jni头文件分析

    一. 首先写了java文件: public class HeaderFile { private native void  doVoid(); native int doShort(); native ...

  7. Java线程入门第三篇

    Java内存模型(jmm) Why:保证多线程正确协同工作 看图说明: 文字解释:线程a和线程b通信过程,首先线程a把本地内存的共享变量更新到主内存中,然后线程b去读取主内存的共享变量,最后更新到自己 ...

  8. Visualforce入门第三篇_2017.3.2

    Visualforce实现显示Record List(列表) 详细见链接:https://trailhead.salesforce.com/modules/visualforce_fundamenta ...

  9. JavaMail入门第四篇 接收邮件

    上一篇JavaMail入门第三篇 发送邮件中,我们学会了如何用JavaMail API提供的Transport类发送邮件,同样,JavaMail API中也提供了一些专门的类来对邮件的接收进行相关的操 ...

随机推荐

  1. 问题 B: Curriculum Vitae

    问题 B: Curriculum Vitae 时间限制: 1 Sec  内存限制: 128 MB提交: 109  解决: 25[提交][状态][讨论版][命题人:acm4302] 题目描述 Hideo ...

  2. 感知器及其Python实现

    感知器是由美国计算机科学家罗森布拉特(F.Roseblatt)于1957年提出的.感知器可谓是最早的人工神经网络.单层感知器是一个具有一层神经元.采用阈值激活函数的前向网络.通过对网络权值的训练,可以 ...

  3. Charles拦截请求

    一.通过Charles抓包,可拦截请求并篡改交互信息 1.可篡改客户端向服务器发起的请求信息(服务器收到的是假消息) 2.可篡改服务器返回给客户端的响应结果(客户端看到的是假消息) 二.篡改用户请求 ...

  4. java算法面试题:编写一个程序,将a.txt文件中的单词与b.txt文件中的单词交替合并到c.txt文件中,a.txt文件中的单词用回车符分隔,b.txt文件中用回车或空格进行分隔。

    package com.swift; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File ...

  5. c#基础之循环探索

    前言在学习基础的语法中循环控制是程序语句控制中的一种,循环在很多的操作中都有应用,例如在获得数据库中的查询的数据之后可以用循环遍历的方式拿到每一行的数据,从而拿到每一个单元格的数据,在文件的操作中也大 ...

  6. 32-1题:不分行从上到下打印二叉树/BFS/deque/queue

    题目 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 考点 1.广度优先遍历 2.binary tree 3.queue 4.deque 思路 按层打印:8.6.10.5.7.9.11 用ST ...

  7. 1207: [HNOI2004]打鼹鼠

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4154  Solved: 1997[Submit][Status][Discuss] Descript ...

  8. JDBC的连接mySql的基本知识

    这只是我自己的随笔博客~,用于偶尔回忆知识,可能存在一些错误,如有错误,欢迎指正~ 首先对于JDBC连接MySQL,要了解基本的框架结构 画的比较烂,大约就是这样的结构 然后看一下具体实现的 代码:: ...

  9. 小技巧之padding-bottom实现等比例图片缩放

    1.padding-bottom 如果用%来表示的话,计算是根据父元素的width的值进行计算的. 例:父元素.wrapper的width是100px,height设置为0, padding-bott ...

  10. json数据格式及json格式化工具推荐

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据. 易于人阅读和编写,同时也易于机器解析和生成. XML也 ...