通過上篇文章hadoop之旅5-idea通過maven搭建hdfs環境,相信大家都可以在idea上做hadoop訪問hdfs檔案系統的開發了。一個雲盤其實就可以基於這樣的系統做出來。有興趣的大家可以試著自己去實戰一下。
今天帶大家在本地執行Mapreduce,進行單詞個數的統計,一般用於除錯。線上模式也很簡單,只需要打好jar包,線上上服務通過 hadoop jar xxxx.jar 包名+類
命令執行即可,可自行探究
MapReduce
MapReduce是一種程式設計模型,用於大規模資料集(大於1TB)的並行運算。他也屬於hadoop的核心元件之一,hdfs是一個分散式檔案系統,MapReduce就是一個分散式計算框架。專門為計算而生
最簡單的流程圖
- 讀取檔案
- map操作
- reduce操作
- 輸出結果檔案
詳細過程圖
在map,reduce中間還有一系列,合併,排序等等過程,系統會將複雜的資料進行整理篩選,最終到達我們需要用程式碼編寫的業務端。我們一般情況做資料離線分析可以只考慮編寫map端,reduce端即可。話不多說直接帶大家上程式碼體會。開始實現
1.首先
在準備好一個輸入檔案input.txt
,放在專案任意一個目錄下,我建的是SpringBoot專案放在resources
下的map_input
目錄下
c 2
c++ 1
java 2
python 1
複製程式碼
2.匯入依賴
<properties>
<hadoop.version>2.7.3</hadoop.version>
</properties>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${hadoop.version}</version>
</dependency>
複製程式碼
3.準備自己map端
實現map端其實很簡單,只需要建立一個類繼承Mapper類,然後實現它的map方法即可。
public class MyMapper extends Mapper<Object, Text, Text, LongWritable> {
/**
*
* @param key 當前行的標識(鍵),一般檔案輸入可以不用管
* @param text 當前行的值
* @param context 上下文內容
* 檔案內容:
* java,c++
* c,java
* python,c
*/
@Override
protected void map(Object key, Text text, Context context) throws IOException, InterruptedException {
//拿到當前輸入的行內容
String line = text.toString();
//拆分當前行,如 java,c++
String[] lines = line.split(",");
for (String word : lines) {
/**
* 也就是在map端,把輸出置為: java 1,c 1,c++ 1等
*/
context.write(new Text(word),new LongWritable(1));
}
}
}
複製程式碼
4.實現Reduce端
同理,繼承Reducer類,實現reduce方法即可
/**
* 前兩個引數:reducer輸入引數,即map輸出的鍵,值集合(相同key的會整合在一起)
* 後兩個引數:reducer 輸出的鍵,值(即最終結果)
* 在reduce裡做累加即可統計出每個單詞的個數
*/
public class MyReduce extends Reducer<Text,LongWritable,Text,LongWritable>{
@Override
protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
/**
* key,values
* 以map裡的輸出的鍵值:如:map裡輸出的是:
* c:[1,1]也可能是 c:[2] ,主要涉及MapReducer執行原理中的 分片合併 過程
* c++:[1]
* java:[1,1]也可能是java:[2]
* python:[1]
*/
long sum = 0; //該單詞總共出現的次數
for (LongWritable value : values) {
sum+=value.get();
}
context.write(key,new LongWritable(sum)); //輸出結果:如,c:2,java:1...
}
}
複製程式碼
5. 實現客戶端程式碼
呼叫程式碼很常規,基本上都是一樣的模板
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
//線上執行在hadoop叢集裡需要配置
//conf.set("fs.defaultFS", "hdfs://master:9000/");//主master訪問路徑
//conf.set("mapreduce.framework.name", "yarn"); //執行框架yarn
//conf.set("yarn.resourcemanager.hostname", "master"); //設定主機
Job job = Job.getInstance(conf); //拿到一個作業job,來執行mapReduce
//設定執行的主類
job.setJarByClass(MapReduceClient.class);
job.setJobName("wordCount"); //設定應用名稱
//設定輸入檔案的位置
FileInputFormat.addInputPaths(job,"J:\\IDEA\\springboot-hadoop\\src\\main\\resources\\map_input");
//設定輸出檔案的位置
FileOutputFormat.setOutputPath(job,new Path("J:\\IDEA\\springboot-hadoop\\src\\main\\resources\\map_output"));
//設定mapper類和reducer類
job.setMapperClass(MyMapper.class);
job.setReducerClass(MyReduce.class);
//設定輸入,輸出型別,map和reduce是一樣的話可以只寫reducer的
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
//執行
job.waitForCompletion(true);
}
複製程式碼
在本地執行有個要求,需要本地hadoop的bin目錄下擁有windows下的執行檔案。大家可以下好hadoop之後直接解壓,然後把windows執行包複製到bin目錄即可
最終的執行結果如下