分散式計算MapReduce究竟是怎麼一回事?
前言
如果要對檔案中的內容進行統計,大家覺得怎麼做呢?一般的思路都是將不同地方的檔案資料讀取到記憶體中,最後集中進行統計。如果資料量少還好,但是面對海量資料、大資料的場景這樣真的合適嗎?不合適的話,那有什麼比較好的方式進行計算呢?不急,看完本文給你答案。
分散式計算思想
我們開啟思路,既然檔案資料遍佈在各個節點上,那麼我們就不把檔案從各個節點載入過來,而是把演算法分到各個節點進行計算,最後統一進行合併處理。這就是所謂的分散式計算。
分散式計算將該應用分解成許多小的部分,分配給多臺計算機進行處理。這樣可以節約整體計算時間,大大提高計算效率。
整個思想的核心就是“先分再合,分而治之”。所謂“分而治之”就是把一個複雜的問題,按照一定的“分解”方法分為等價的規模較小的若干部分,然後逐個解決,分別找出各部分的結果,然後把各部分的結果組成整個問題的最終結果。
那麼Hadoop也借鑑了這樣的思想,設計出了MapReduce計算框架。那麼MapReduce框架具體設計上有什麼亮點呢?
MapReduce設計思想
Hadoop在設計MapReduce的時候,吸取了分散式計算中分而治之的思想,同時需要考慮更多細節的問題。
(1)如何對付大資料處理場景
對相互間不具有計算依賴關係的大資料計算任務,實現並行最自然的辦法就是採取MapReduce分而治之的策略。
首先Map階段進行拆分,把大資料拆分成若干份小資料,多個程式同時平行計算產生中間結果;然後是Reduce聚
合階段,通過程式對並行的結果進行最終的彙總計算,得出最終的結果。
不可拆分的計算任務或相互間有依賴關係的資料無法進行平行計算。
(2)構建抽象程式設計模型
MapReduce借鑑了函式式語言中的思想,用Map和Reduce兩個函式提供了高層的並行程式設計抽象模型。
map: 對一組資料元素進行某種重複式的處理;
reduce: 對Map的中間結果進行某種進一步的結果整理。
MapReduce中定義瞭如下的Map和Reduce兩個抽象的程式設計介面,由使用者去程式設計實現:
map: (k1; v1) → (k2; v2)
reduce: (k2; [v2]) → (k3; v3)
通過以上兩個程式設計介面,大家可以看出MapReduce
處理的資料型別是<key,value>
鍵值對。
(3)統一架構、隱藏底層細節
如何提供統一的計算框架,如果沒有統一封裝底層細節,那麼程式設計師則需要考慮諸如資料儲存、劃分、分發、結果
收集、錯誤恢復等諸多細節;為此,MapReduce設計並提供了統一的計算框架,為程式設計師隱藏了絕大多數系統層
面的處理細節。
MapReduce最大的亮點在於通過抽象模型和計算框架把需要做什麼(what need to do)
與具體怎麼做(how to do)
分開了,為程式設計師提供一個抽象和高層的程式設計介面和框架。
程式設計師僅需要關心其應用層的具體計算問題,僅需編寫少量的處理應用本身計算問題的業務程式程式碼。
至於如何具體完成這個平行計算任務所相關的諸多系統層細節被隱藏起來,交給計算框架去處理: 從分佈程式碼的執行,到大到數千小到單個節點叢集的自動排程使用。
MapReduce介紹
Hadoop MapReduce
是一個分散式計算框架,用於輕鬆編寫分散式應用程式,這些應用程式以可靠,容錯的方式並行處理大型硬體叢集(數千個節點)上的大量資料(多TB資料集)。
MapReduce是一種面向海量資料處理的一種指導思想,也是一種用於對大規模資料進行分散式計算的程式設計模型。
MapReduce特點
- 易於程式設計
Mapreduce框架提供了用於二次開發的介面;簡單地實現一些介面,就可以完成一個分散式程式。任務計算交給計算框架去處理,將分散式程式部署到hadoop叢集上執行,叢集節點可以擴充套件到成百上千個等。
- 良好的擴充套件性
當計算機資源不能得到滿足的時候,可以通過增加機器來擴充套件它的計算能力。基於MapReduce的分散式計算得特點可以隨節點數目增長保持近似於線性的增長,這個特點是MapReduce處理海量資料的關鍵,通過將計算節點增至幾百或者幾千可以很容易地處理數百TB甚至PB級別的離線資料。
- 高容錯性
Hadoop叢集是分散式搭建和部署得,任何單一機器節點宕機了,它可以把上面的計算任務轉移到另一個節點上執行,不影響整個作業任務得完成,過程完全是由Hadoop內部完成的。
- 適合海量資料的離線處理
可以處理GB、TB和PB級別得資料量。
MapReduce侷限性
MapReduce雖然有很多的優勢,也有相對得侷限性,侷限性不代表不能做,而是在有些場景下實現的效果比較差,並不適合用MapReduce來處理,主要表現在以下結果方面:
- 實時計算效能差
MapReduce主要應用於離線作業,無法作到秒級或者是亞秒級得資料響應。
- 不能進行流式計算
流式計算特點是資料是源源不斷得計算,並且資料是動態的;而MapReduce作為一個離線計算框架,主要是針對靜態資料集得,資料是不能動態變化得。
MapReduce實戰
WordCount
算是大資料計算領域經典的入門案例,相當於Hello World。主要是統計指定檔案中,每個單詞出現的總次數。
雖然WordCount業務極其簡單,但是希望能夠通過案例感受背後MapReduce的執行流程和預設的行為機制,這才是關鍵。
- Map階段程式碼實現
- 實現了map介面,把輸入的資料經過切割,全部標記1,因此輸出就是<單詞,1>。
- Reduce階段程式碼實現
- 實現了reduce介面,對所有的1進行累加求和,就是單詞的總次數
- 啟動程式碼
- 執行
hadoop jar hadoop-mapreduce-examples-3.3.0.jar wordcount
/input /output
- 第一個引數:wordcount表示執行單詞統計任務;
- 第二個引數:指定輸入檔案的路徑;
- 第三個引數:指定輸出結果的路徑(該路徑不能已存在)
- 檢視執行結果
最終可以在/output目錄下看到輸出的結果
MapReduce執行流程
從資源執行層面,一個完整的MapReduce程式在分散式執行時有三類程式,如下所示:
-
MRAppMaster
:負責整個MR程式的過程排程及狀態協調 -
MapTask
:負責map階段的整個資料處理流程 -
ReduceTask
:負責reduce階段的整個資料處理流程
MapReduce任務優先會提交到Yarn元件上,這個主要是用來管理資源的,因為計算需要CPU、記憶體等資源。首先會執行1個MRAppMaster
程式,主要負責整個MR程式的過程排程及狀態協調。然後執行多個MapTask
,最後執行ReduceTask
。
從業務邏輯層面上,以上面的wordCount為例,它的執行流程如下圖所示:
Map階段執行流程
- 第一階段:把輸入目錄下檔案按照一定的標準逐個進行邏輯切片,形成切片規劃。預設
Split size = Block size(128M)
,每一個切片由一個MapTask
處理。
- 第二階段:對切片中的資料按照一定的規則讀取解析返回
<key,value>
對。預設是按行讀取資料。key是每一行的起始位置偏移量,value是本行的文字內容。
- 第三階段:呼叫Mapper類中的map方法處理資料。每讀取解析出來的一個
<key,value>
,呼叫一次map方法。
- 第四階段:按照一定的規則對Map輸出的鍵值對進行分割槽partition。預設不分割槽,因為只有一個
reducetask
。分割槽的數量就是reducetask執行的數量。 - 第五階段:Map輸出資料寫入記憶體緩衝區,達到比例溢位到磁碟上。溢位spill的時候根據key進行排序sort。預設根據key字典序排序。
- 第六階段:對所有溢位檔案進行最終的merge合併,成為一個檔案。
Reduce階段執行過程
- 第一階段:ReduceTask會主動從MapTask複製拉取屬於需要自己處理的資料。
- 第二階段:把拉取來資料,全部進行合併merge,即把分散的資料合併成一個大的資料。再對合並後的資料排序。
- 第三階段是對排序後的鍵值對呼叫reduce方法。鍵相等的鍵值對呼叫一次reduce方法。最後把這些輸出的鍵值對寫入到HDFS檔案中。
shuffle階段
-
Shuffle
的本意是洗牌、混洗的意思,把一組有規則的資料儘量打亂成無規則的資料。 - 而在MapReduce中,Shuffle更像是洗牌的逆過程,指的是將map端的無規則輸出按指定的規則“打亂”成具有一定規則的資料,以便reduce端接收處理。
- 一般把從Map產生輸出開始到Reduce取得資料作為輸入之前的過程稱作shuffle。
以上就是整個MapReduce執行的整個流程。
總結
MapReduce是Hadoop提供的一個分散式計算框架,對於大資料開發人員來說,只要關注於自己的業務,實現他們提供的Map和Reduce介面,接下來底層都交給Hadoop來處理。但是MapReduce已經日薄西山,企業用的也越來越少了,慢慢被Spark、Flink等計算引擎代替,主要原因還是太慢,比如shuffle階段中頻繁涉及到資料在記憶體、磁碟之間的多次往復,但是這種計算思想還是很值得一學的。
如果本文對你有幫助的話,請留下一個贊吧
歡迎關注個人公眾號——JAVA旭陽
更多學習資料請移步:程式設計師成神之路