Hadoop – MapReduce

Hadoop – MapReduce


MapReduce 是一个框架,我们可以使用它编写应用程序,以可靠的方式在大型商用硬件集群上并行处理大量数据。

什么是 MapReduce?

MapReduce是一种基于java的分布式计算处理技术和程序模型。MapReduce 算法包含两个重要的任务,即 Map 和 Reduce。Map 获取一组数据并将其转换为另一组数据,其中单个元素被分解为元组(键/值对)。其次,reduce 任务,它将地图的输出作为输入,并将这些数据元组组合成一个较小的元组集。正如 MapReduce 名称的顺序所暗示的那样,reduce 任务总是在 map 作业之后执行。

MapReduce 的主要优点是易于在多个计算节点上扩展数据处理。在 MapReduce 模型下,数据处理原语称为映射器和化简器。将数据处理应用程序分解为映射器和化器有时并非易事。但是,一旦我们以 MapReduce 形式编写应用程序,将应用程序扩展到在集群中运行数百、数千甚至数万台机器仅仅是配置更改。这种简单的可扩展性吸引了许多程序员使用 MapReduce 模型。

算法

  • 通常 MapReduce 范式是基于将计算机发送到数据所在的位置!

  • MapReduce 程序分三个阶段执行,分别是map 阶段、shuffle 阶段和reduce 阶段。

    • Map stage – 地图或映射器的工作是处理输入数据。通常输入数据以文件或目录的形式存储在Hadoop文件系统(HDFS)中。输入文件逐行传递给映射器函数。映射器处理数据并创建几个小数据块。

    • Reduce 阶段– 此阶段是Shuffle阶段和Reduce阶段的组合。Reducer 的工作是处理来自映射器的数据。处理后,它会产生一组新的输出,这些输出将存储在 HDFS 中。

  • 在 MapReduce 作业期间,Hadoop 将 Map 和 Reduce 任务发送到集群中的相应服务器。

  • 该框架管理数据传递的所有细节,例如发出任务、验证任务完成以及在节点之间的集群周围复制数据。

  • 大多数计算发生在具有本地磁盘上的数据的节点上,从而减少了网络流量。

  • 完成给定的任务后,集群收集并缩减数据以形成适当的结果,并将其发送回Hadoop服务器。

MapReduce 算法

输入和输出(Java 视角)

MapReduce 框架对 <key, value> 对进行操作,即框架将作业的输入视为一组 <key, value> 对,并产生一组 <key, value> 对作为作业的输出,可以想象有不同的类型。

键和值类应该由框架以序列化方式进行,因此需要实现 Writable 接口。此外,关键类必须实现 Writable-Comparable 接口以方便框架的排序。MapReduce 作业的输入和输出类型-(输入)<k1, v1> → map → <k2, v2> → reduce → <k3, v3>(输出)。

输入 输出
Map <k1​​, v1> 列表 (<k2, v2>)
Reduce <k2, 列表(v2)> 列表 (<k3, v3>)

术语

  • PayLoad – 应用程序实现 Map 和 Reduce 功能,并构成工作的核心。

  • Mapper – Mapper 将输入键/值对映射到一组中间键/值对。

  • NamedNode – 管理 Hadoop 分布式文件系统 (HDFS) 的节点。

  • DataNode – 在进行任何处理之前预先显示数据的节点。

  • MasterNode – JobTracker 运行并接受来自客户端的作业请求的节​​点。

  • SlaveNode – Map 和 Reduce 程序运行的节点。

  • JobTracker – 安排作业并跟踪分配作业到任务跟踪器。

  • 任务跟踪器– 跟踪任务并向 JobTracker 报告状态。

  • 作业– 程序是跨数据集执行 Mapper 和 Reducer。

  • 任务– 在数据切片上执行 Mapper 或 Reducer。

  • 任务尝试– 尝试在 SlaveNode 上执行任务的特定实例。

示例场景

下面给出了有关组织的电力消耗的数据。它包含每月的用电量和各年的年平均值。

二月 三月 四月 可能 七月 八月 九月 十月 十一月 十二月 平均
1979 23 23 2 43 24 25 26 26 26 26 25 26 25
1980 26 27 28 28 28 30 31 31 31 30 30 30 29
1981 31 32 32 32 33 34 35 36 36 34 34 34 34
1984 39 38 39 39 39 41 42 43 40 39 38 38 40
1985 38 39 39 39 39 41 41 41 00 40 39 39 45

如果将上述数据作为输入,我们必须编写应用程序来处理它并产生诸如查找最大使用年份、最小使用年份等结果。对于记录数有限的程序员来说,这是一个过渡。他们将简单地编写逻辑以产生所需的输出,并将数据传递给编写的应用程序。

但是,想想代表特定国家所有大型工业自其形成以来的电力消耗的数据。

当我们编写应用程序来处理这样的大量数据时,

  • 它们将需要大量时间来执行。

  • 当我们将数据从源移动到网络服务器等时,将会有大量的网络流量。

为了解决这些问题,我们有了 MapReduce 框架。

输入数据

上述数据保存为sample.txt并作为输入给出。输入文件如下所示。

1979   23   23   2   43   24   25   26   26   26   26   25   26  25 
1980   26   27   28  28   28   30   31   31   31   30   30   30  29 
1981   31   32   32  32   33   34   35   36   36   34   34   34  34 
1984   39   38   39  39   39   41   42   43   40   39   38   38  40 
1985   38   39   39  39   39   41   41   41   00   40   39   39  45 

示例程序

下面给出了使用 MapReduce 框架的示例数据的程序。

package hadoop; 

import java.util.*; 

import java.io.IOException; 
import java.io.IOException; 

import org.apache.hadoop.fs.Path; 
import org.apache.hadoop.conf.*; 
import org.apache.hadoop.io.*; 
import org.apache.hadoop.mapred.*; 
import org.apache.hadoop.util.*; 

public class ProcessUnits {
   //Mapper class 
   public static class E_EMapper extends MapReduceBase implements 
   Mapper<LongWritable ,/*Input key Type */ 
   Text,                /*Input value Type*/ 
   Text,                /*Output key Type*/ 
   IntWritable>        /*Output value Type*/ 
   {
      //Map function 
      public void map(LongWritable key, Text value, 
      OutputCollector<Text, IntWritable> output,   
      
      Reporter reporter) throws IOException { 
         String line = value.toString(); 
         String lasttoken = null; 
         StringTokenizer s = new StringTokenizer(line,"\t"); 
         String year = s.nextToken(); 
         
         while(s.hasMoreTokens()) {
            lasttoken = s.nextToken();
         }
         int avgprice = Integer.parseInt(lasttoken); 
         output.collect(new Text(year), new IntWritable(avgprice)); 
      } 
   }
   
   //Reducer class 
   public static class E_EReduce extends MapReduceBase implements Reducer< Text, IntWritable, Text, IntWritable > {
   
      //Reduce function 
      public void reduce( Text key, Iterator <IntWritable> values, 
      OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException { 
         int maxavg = 30; 
         int val = Integer.MIN_VALUE; 
            
         while (values.hasNext()) { 
            if((val = values.next().get())>maxavg) { 
               output.collect(key, new IntWritable(val)); 
            } 
         }
      } 
   }

   //Main function 
   public static void main(String args[])throws Exception { 
      JobConf conf = new JobConf(ProcessUnits.class); 
      
      conf.setJobName("max_eletricityunits"); 
      conf.setOutputKeyClass(Text.class);
      conf.setOutputValueClass(IntWritable.class); 
      conf.setMapperClass(E_EMapper.class); 
      conf.setCombinerClass(E_EReduce.class); 
      conf.setReducerClass(E_EReduce.class); 
      conf.setInputFormat(TextInputFormat.class); 
      conf.setOutputFormat(TextOutputFormat.class); 
      
      FileInputFormat.setInputPaths(conf, new Path(args[0])); 
      FileOutputFormat.setOutputPath(conf, new Path(args[1])); 
      
      JobClient.runJob(conf); 
   } 
} 

将上述程序另存为ProcessUnits.java。下面解释程序的编译和执行。

工艺单元程序的编译与执行

让我们假设我们位于 Hadoop 用户的主目录中(例如 /home/hadoop)。

按照下面给出的步骤编译和执行上述程序。

步骤1

下面的命令是创建一个目录来存放编译后的java类。

$ mkdir units 

第2步

下载Hadoop-core-1.2.1.jar,用于编译和执行MapReduce程序。访问以下链接mvnrepository.com下载 jar。让我们假设下载的文件夹是/home/hadoop/。

第 3 步

以下命令用于编译ProcessUnits.java程序并为该程序创建 jar。

$ javac -classpath hadoop-core-1.2.1.jar -d units ProcessUnits.java 
$ jar -cvf units.jar -C units/ . 

第四步

以下命令用于在 HDFS 中创建输入目录。

$HADOOP_HOME/bin/hadoop fs -mkdir input_dir 

第 5 步

以下命令用于将名为sample.txt的输入文件复制到HDFS 的输入目录中。

$HADOOP_HOME/bin/hadoop fs -put /home/hadoop/sample.txt input_dir 

第 6 步

以下命令用于验证输入目录中的文件。

$HADOOP_HOME/bin/hadoop fs -ls input_dir/ 

第 7 步

以下命令用于通过从输入目录中获取输入文件来运行 Eleunit_max 应用程序。

$HADOOP_HOME/bin/hadoop jar units.jar hadoop.ProcessUnits input_dir output_dir 

稍等片刻,直到文件被执行。执行后,如下图,输出将包含输入分割数、Map任务数、reducer任务数等。

INFO mapreduce.Job: Job job_1414748220717_0002 
completed successfully 
14/10/31 06:02:52 
INFO mapreduce.Job: Counters: 49 
   File System Counters 
 
FILE: Number of bytes read = 61 
FILE: Number of bytes written = 279400 
FILE: Number of read operations = 0 
FILE: Number of large read operations = 0   
FILE: Number of write operations = 0 
HDFS: Number of bytes read = 546 
HDFS: Number of bytes written = 40 
HDFS: Number of read operations = 9 
HDFS: Number of large read operations = 0 
HDFS: Number of write operations = 2 Job Counters 


   Launched map tasks = 2  
   Launched reduce tasks = 1 
   Data-local map tasks = 2  
   Total time spent by all maps in occupied slots (ms) = 146137 
   Total time spent by all reduces in occupied slots (ms) = 441   
   Total time spent by all map tasks (ms) = 14613 
   Total time spent by all reduce tasks (ms) = 44120 
   Total vcore-seconds taken by all map tasks = 146137 
   Total vcore-seconds taken by all reduce tasks = 44120 
   Total megabyte-seconds taken by all map tasks = 149644288 
   Total megabyte-seconds taken by all reduce tasks = 45178880 
   
Map-Reduce Framework 
 
   Map input records = 5  
   Map output records = 5   
   Map output bytes = 45  
   Map output materialized bytes = 67  
   Input split bytes = 208 
   Combine input records = 5  
   Combine output records = 5 
   Reduce input groups = 5  
   Reduce shuffle bytes = 6  
   Reduce input records = 5  
   Reduce output records = 5  
   Spilled Records = 10  
   Shuffled Maps  = 2  
   Failed Shuffles = 0  
   Merged Map outputs = 2  
   GC time elapsed (ms) = 948  
   CPU time spent (ms) = 5160  
   Physical memory (bytes) snapshot = 47749120  
   Virtual memory (bytes) snapshot = 2899349504  
   Total committed heap usage (bytes) = 277684224
     
File Output Format Counters 
 
   Bytes Written = 40 

第 8 步

以下命令用于验证输出文件夹中的结果文件。

$HADOOP_HOME/bin/hadoop fs -ls output_dir/ 

步骤 9

以下命令用于查看Part-00000文件中的输出该文件由 HDFS 生成。

$HADOOP_HOME/bin/hadoop fs -cat output_dir/part-00000 

下面是 MapReduce 程序生成的输出。

1981    34 
1984    40 
1985    45 

第 10 步

以下命令用于将输出文件夹从 HDFS 复制到本地文件系统进行分析。

$HADOOP_HOME/bin/hadoop fs -cat output_dir/part-00000/bin/hadoop dfs get output_dir /home/hadoop 

重要命令

所有 Hadoop 命令都由$HADOOP_HOME/bin/hadoop命令调用运行不带任何参数的 Hadoop 脚本会打印所有命令的描述。

用法– hadoop [–config confdir] 命令

下表列出了可用的选项及其说明。

Sr.No. 选项和说明
1

namenode -format

格式化 DFS 文件系统。

2

secondarynamenode

运行 DFS 辅助名称节点。

3

namenode

运行 DFS namenode。

4

datanode

运行 DFS 数据节点。

5

dfsadmin

运行 DFS 管理客户端。

6

mradmin

运行 Map-Reduce 管理客户端。

7

fsck

运行 DFS 文件系统检查实用程序。

8

fs

运行通用文件系统用户客户端。

9

balancer

运行集群平衡实用程序。

10

oiv

将离线 fsimage 查看器应用于 fsimage。

11

fetchdt

从 NameNode 获取委托令牌。

12

jobtracker

运行 MapReduce 作业跟踪器节点。

13

pipes

运行管道作业。

14

tasktracker

运行 MapReduce 任务跟踪器节点。

15

historyserver

将作业历史服务器作为独立的守护进程运行。

16

job

操作 MapReduce 作业。

17

queue

获取有关 JobQueue 的信息。

18

version

打印版本。

19

jar <jar>

运行一个 jar 文件。

20

distcp <srcurl> <desturl>

递归复制文件或目录。

21

distcp2 <srcurl> <desturl>

DistCp 版本 2。

22

archive -archiveName NAME -p <parent path> <src>* <dest>

创建一个 hadoop 存档。

23

classpath

打印获取 Hadoop jar 和所需库所需的类路径。

24

daemonlog

获取/设置每个守护进程的日志级别

如何与 MapReduce 作业交互

用法 – hadoop 作业 [GENERIC_OPTIONS]

以下是 Hadoop 作业中可用的通用选项。

Sr.No. GENERIC_OPTION & 描述
1

-submit <job-file>

提交作业。

2

-status <job-id>

打印地图并减少完成百分比和所有作业计数器。

3

-counter <job-id> <group-name> <countername>

打印计数器值。

4

-kill <job-id>

杀死工作。

5

-events <job-id> <fromevent-#> <#-of-events>

打印 jobtracker 在给定范围内收到的事件详细信息。

6

-history [all] <jobOutputDir> – history < jobOutputDir>

打印作业详细信息、失败和终止的提示详细信息。可以通过指定 [all] 选项查看有关作业的更多详细信息,例如成功的任务和为每个任务所做的任务尝试。

7

-list[all]

显示所有作业。-list 仅显示尚未完成的作业。

8

-kill-task <task-id>

杀死任务。被杀死的任务不计入失败的尝试。

9

-fail-task <task-id>

任务失败。失败的任务被计入失败的尝试。

10

-set-priority <job-id> <priority>

更改作业的优先级。允许的优先级值为 VERY_HIGH、HIGH、NORMAL、LOW、VERY_LOW

查看作业状态

$ $HADOOP_HOME/bin/hadoop job -status <JOB-ID> 
e.g. 
$ $HADOOP_HOME/bin/hadoop job -status job_201310191043_0004 

查看作业输出目录的历史记录

$ $HADOOP_HOME/bin/hadoop job -history <DIR-NAME> 
e.g. 
$ $HADOOP_HOME/bin/hadoop job -history /user/expert/output 

杀死工作

$ $HADOOP_HOME/bin/hadoop job -kill <JOB-ID> 
e.g. 
$ $HADOOP_HOME/bin/hadoop job -kill job_201310191043_0004 

觉得文章有用?

点个广告表达一下你的爱意吧 !😁