Hadoop - MapReduce
MapReduce是一個框架,我們可以編寫應用程序,以可靠的方式并行處理大量商品硬件的大量數據。
原文鏈接:http://blogxinxiucan.sh1.newtouch.com/2017/07/17/Hadoop-MapReduce/
什么是MapReduce?
MapReduce
是基于java的分布式計算的處理技術和程序模型。MapReduce算法包含兩個重要任務,即Map和Reduce。地圖獲取一組數據并將其轉換為另一組數據,其中單個元素分解為元組(鍵/值對)。其次,減少任務,將地圖的輸出作為輸入,并將這些數據元組合并成一組較小的元組。按照MapReduce名稱的順序,reduce任務總是在地圖作業之后執行。
MapReduce的主要優點是可以輕松地在多個計算節點上進行數據處理。在MapReduce模型下,數據處理原語稱為映射器和還原器。將數據處理應用程序分解成映射器和還原器有時是不重要的。但是,一旦我們在MapReduce表單中編寫應用程序,將應用程序擴展到集群中數以百計,甚至數萬臺計算機上的計算機只是配置更改。這種簡單的可擴展性是吸引了許多程序員使用MapReduce模型。
算法
- 一般MapReduce范例通常是將計算機發送到數據所在的地方!
- MapReduce程序分三個階段執行,分別是地圖階段,洗牌階段和減少階段。
地圖階段:地圖或映射器的作業是處理輸入數據。通常,輸入數據是以文件或目錄的形式存儲在Hadoop文件系統(HDFS)中。輸入文件逐行傳遞給映射器函數。映射器處理數據并創建幾個小塊數據。
減少階段:這個階段是洗牌階段和減少階段的組合。Reducer的工作是處理來自映射器的數據。在處理之后,它產生一組新的輸出,將其存儲在HDFS中。
- 在MapReduce作業期間,Hadoop將Map和Reduce任務發送到集群中的相應服務器。
- 該框架管理數據傳遞的所有細節,如發布任務,驗證任務完成,以及在節點之間圍繞集群復制數據。
- 大多數計算發生在具有本地磁盤上的數據的節點上,從而減少網絡流量。
- 在完成給定任務后,集群收集并減少數據以形成適當的結果,并將其發送回Hadoop服務器。
MapReduce算法
輸入和輸出(Java Perspective)
MapReduce框架在<key,value>
對上運行,即框架將作業的輸入視為一組<key,value>
對,并生成一組<key,value>
對作為作業的輸出,可以想象不同的類型。
關鍵和值類應該由框架以序列化的方式,因此需要實現Writable接口。另外,關鍵類必須實現Writable-Comparable接口,以便于框架進行排序。MapReduce作業的輸入和輸出類型:(輸入)<k1,v1> - > map - > <k2,v2> - > reduce - > <k3,v3>(輸出)
。
0 | 輸入 | 產量 |
---|---|---|
地圖 | <k1??,v1> |
列表(<k2,v2>)
|
減少 | <k2,list(v2)> |
列表(<k3,v3> ) |
術語
- PayLoad - 應用程序實現Map和Reduce功能,并構成工作的核心。
- Mapper - Mapper將輸入鍵/值對映射到一組中間鍵/值對。
- NamedNode - 管理Hadoop分布式文件系統(HDFS)的節點。
- DataNode - 數據在進行任何處理之前提前呈現的節點。
- MasterNode - JobTracker運行的節點,并接收來自客戶端的作業請求。
- SlaveNode - 運行Map和Reduce程序的節點。
- JobTracker - 調度作業并跟蹤分配作業到任務跟蹤器。
- Task Tracker - 跟蹤任務并向JobTracker報告狀態。
- Job - 程序是跨數據集執行映射器和還原器。
- Task - 在一片數據上執行Mapper或Reducer。
- Task Attempt - 嘗試在SlaveNode上執行任務的特定實例。
示例場景
以下是有關組織的電力消耗的數據。它包含每年的電力消耗和各年的年平均值。
如果以上數據作為輸入,我們必須編寫應用程序來處理它,并產生結果,例如查找最大使用年份,最小使用年數等。這是一個有限數量記錄的程序員的過程。他們只需編寫邏輯來產生所需的輸出,并將數據傳遞給寫入的應用程序。
但是,考慮到自形成以來,特定國家所有大型工業的電力消耗量的數據。
當我們編寫應用程序來處理這樣的批量數據時,
- 他們需要很多時間來執行。
- 當我們從數據源到網絡服務器等移動數據時,會有一個沉重的網絡流量。 為了解決這些問題,我們提供了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程序。訪問以下鏈接http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-core/1.2.1
下載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/ .
步驟4
以下命令用于在HDFS中創建輸入目錄。
$HADOOP_HOME/bin/hadoop fs -mkdir input_dir
步驟5
以下命令用于在HDFS的輸入目錄中復制名為sample.txt的輸入文件。
$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]命令
下表列出了可用的選項及其說明。
選項 | 描述 |
---|---|
namenode -format | 格式化DFS文件系統。 |
secondarynamenode | 運行DFS輔助節點。 |
namenode | 運行DFS namenode。 |
datanode | 運行DFS datanode。 |
dfsadmin | 運行DFS管理客戶機。 |
mradmin | 運行Map-Reduce管理客戶端。 |
fsck | 運行DFS文件系統檢查實用程序。 |
fs | 運行通用文件系統用戶客戶機。 |
balancer | 運行集群平衡實用程序。 |
oiv | 將離線fsimage查看器應用到fsimage。 |
fetchdt | 從NameNode獲取一個委托令牌。 |
jobtracker | 運行MapReduce作業跟蹤器節點。 |
pipes | 運行管道工作。 |
tasktracker | 運行MapReduce任務跟蹤器節點。 |
historyserver | 將作業歷史記錄服務器作為獨立守護程序運行。 |
job | 操縱MapReduce作業。 |
queue | 獲取有關JobQueues的信息。 |
version | 打印版本。 |
jar <jar> | 運行一個jar文件。 |
distcp <srcurl> <desturl> | 遞歸復制文件或目錄。 |
distcp2 <srcurl> <desturl> | DistCp版本2。 |
archive -archiveName NAME -p | 創建hadoop存檔。 |
<parent path> <src>* <dest> | |
classpath | 打印獲取Hadoop jar和所需庫所需的類路徑。 |
daemonlog | 獲取/設置每個守護進程的日志級別 |
如何與MapReduce工作進行交互
用法:hadoop作業[GENERIC_OPTIONS]
以下是Hadoop作業中可用的通用選項。
GENERIC_OPTIONS | 描述 |
---|---|
-submit <job-file> | 提交作業 |
-status <job-id> | 打印地圖并減少完成百分比和所有作業計數器。 |
-counter <job-id> <group-name> <countername> | 打印計數器值。 |
-kill <job-id> | 殺死了這個工作。 |
-events <job-id> <fromevent-#> <#-of-events> | 打印給定范圍的jobtracker收到的事件的詳細信息。 |
-history [all] <jobOutputDir> - history < jobOutputDir> | 打印作業詳細信息,失敗并殺死提示詳細信息。可以通過指定[all]選項來查看有關作業的更多詳細信息,例如為每個任務執行的成功任務和任務嘗試。 |
-list[all] | 顯示所有作業。-list僅顯示尚未完成的作業。 |
-kill-task <task-id> | 殺死任務。殺死的任務不計入失敗的嘗試。 |
-fail-task <task-id> | 無法完成任務 失敗的任務會計入失敗的嘗試次數。 |
-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