MapReduce 編程模型 & WordCount 示例

来源:https://www.cnblogs.com/justdojava/archive/2019/08/01/11271080.html
-Advertisement-
Play Games

學習大數據接觸到的第一個編程思想 MapReduce。 前言 之前在學習大數據的時候,很多東西很零散的做了一些筆記,但是都沒有好好去整理它們,這篇文章也是對之前的筆記的整理,或者叫輸出吧。一來是加深自己的理解,二來是希望這些東西能幫助想要學習大數據或者說正在學習大數據的朋友。如果你看到裡面的東西,讓 ...


 

學習大數據接觸到的第一個編程思想 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 知識體系/面試必看資料。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在JavaScript中,有一個內置對象Date,它重要的一個作用就是實現了時間的時刻更新,通過代碼來創造一個實實在在的時間表。 代碼例子: ...
  • 以上可以看到,如果單獨定義一個變數,獨自訪問該變數的值時,訪問速度要比定義多個變數要慢。 理由的話,應該是JavaScript中訪問變數中具體值時:【theVar1】的形式要比【theVar.theVar1】要快。也就是說,【多個具有聯繫的常量值獨自定義成多個變數】的做法的效率要比【多個具有聯繫的常 ...
  •      學過JavaScript 腳本語言的都應該接觸過setInterval 函數.如何使用我想大家都知道,但是有時候對於剛剛接觸JavaScript的朋友來講,還是會在使用的時候碰到這樣或那樣的問題而感到困惑!以下是經常在QQ群中碰到問的最多的問題。如下圖: &n ...
  • JavaScript是一門函數式的面向對象編程語言。瞭解函數將會是瞭解對象創建和操作、原型及原型方法、模塊化編程等的重要基礎。函數包含一組語句,它的主要功能是代碼復用、隱藏信息和組合調用。我們編程就是把一個需求拆分成若幹函數和數據結構的組合實現,其中演算法又是實現正確函數的方法論。我們先介紹基礎知識: ...
  • 今天使用v-for指令的時候遇到一個錯誤 [Vue warn]: Error in render: "TypeError: Cannot read property 'children' of undefined" 頁面使用代碼 報錯原因: 我猜測使用了嵌套屬性的原因,在頁面中無法解析出具體屬性值, ...
  • 對於過度動畫如果要同時渲染整個列表時,可以使用transition-group組件。 transition-group組件的props和transition組件類似,不同點是transition-group組件的props是沒有mode屬性的,另外多了以下兩個props tag 標簽名 moveCl ...
  • layui.user一個頁面只能有一個,寫多了會實現js效果 上傳圖片官方文檔有很多功能,但是演示的代碼只是一個一個功能演示,如果要綜合起來js代碼不是簡單的拼湊,需要放在指定位置,比如下麵的限制文件大小。 ...
  • [toc] 前言 時間飛逝,轉眼初夏已過,尤記得以前讀大學的時候,夏季最快樂的時光就是和小伙伴們在球場上打完球後去校門附近的燒烤攤擼串喝酒,那種感覺真是大快人心,怎一個爽字了得。不過有時也會遇到特殊情況,在擼串時攤主突然告知要收攤,連忙向我們賠禮道歉,原因是城管將至。我們無奈只能中斷擼串過程,帶著無 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...