從分治演算法到 Hadoop MapReduce

2022-09-15 20:21:13 字數 2859 閱讀 5297

要說 hadoop mapreduce 就不得不說分治演算法,而分治演算法其實說白了,就是四個字分而治之。其實就是將乙個複雜的問題分解成多組相同或類似的子問題,對這些子問題再分,然後再分。直到最後的子問題可以簡單得求解。

要具體介紹分治演算法,那就不得不說乙個很經典的排序演算法 -- 歸併排序。這裡不說它的具體演算法**,只說明它的主要思想。而歸併排序的思想正是分治思想。

歸併排序採用遞迴的方式,每次都將乙個陣列分解成更小的兩個陣列,再對這兩個陣列進行排序,不斷遞迴下去。直到分解成最簡單形式的兩個陣列的時候,再將這乙個個分解後的陣列進行合併。這就是歸併排序。

我們可以看到,初始的陣列是:

第一次分解後,變成兩個陣列:,

分解到最後為 5 個陣列:,,,,

然後分別合併並排序,最後排序完成:

上述的例子這是比較簡單的情況,那麼我們想想看,當這個陣列很大的時候又該怎麼辦呢?比如這個陣列達到 100 gb大小,那麼在一台機器上肯定是無法實現或是效率較為低下的。

那一台機器不行,那我們可以拆分到多台機器中去嘛。剛好使用分治演算法將乙個任務可以拆分成多個小任務,並且這多個小任務間不會相互干擾,可以獨立計算。那麼我們可以拆分這個陣列,將這個陣列拆分成 20 個塊,每個的大小為 5 gb。然後將這每個 5 gb的塊分散到各個不同的機器中去執行,最後再將處理的結果返回,讓**機器再進行一次完整的排序,這樣無疑速度上會提公升很多。

上述這個過程就是 hadoop mapreduce 的大致原理了。

map 和 reduce 其實是函式式程式設計中的兩個語義。map 和迴圈 for 類似,只不過它有返回值。比如對乙個 list 進行 map 操作,它就會遍歷 list 中的所有元素,然後根據每個元素處理後的結果返回乙個新的值。下面這個例子就是利用 map 函式,將 list 中每個元素從 int 型別 轉換為 string 型別。

val a:list[int] = list(1,2,3,4)

val b:list[string] = a.map(num => (num.tostring))

而 reduce 在函式式程式設計的作用則是進行資料歸約。reduce 方法需要傳入兩個引數,然後會遞迴得對每乙個引數執行運算。還是用乙個例子來說明:

val list:list[int] = list(1,2,3,4,5)

//運算順序是:1-2 = -1; -1-3 = -4; -4-4 = -8; -8-5 = -13;

//所以結果等於 -13

list.reduce(_ - _)

hadoop mapreduce 和函式式中的 map reduce 還是比較類似的,只是它是一種程式設計模型。我們來看看 wordcount 的例子就明白了。

在這個 wordcount 程式中,hadoop mapreduce 會對輸入先進行切分,這一步其實就是分治中的過程。切分後不同部分就會讓不同的機器去執行 map 操作。而後便是 shuffle,這一階段會將不相同的單詞加到一起,最後再進行 reduce 。

這個 wordcount 程式是官方提供的乙個簡易的 demo,更複雜的任務需要自己分解成 hadoop mapreduce 模型的**然後執行。

所謂 mapreduce 的意思是任何的事情只要都嚴格遵循 map shuffle reduce 三個階段就好。其中shuffle是系統自己提供的而map和reduce則使用者需要寫**。

當碰到乙個任務的時候,我們需要將它解析成 map reduce 的處理方式然後編寫 hadoop mapreduce **來實現。我看過乙個比喻很貼切,hadoop mapreduce 這個東西這就像是說我們有一把大砍刀,乙個錘子。世界上的萬事萬物都可以先砍幾刀再錘幾下,就能搞定。至於刀怎麼砍,錘子怎麼錘,那就算個人的手藝了。

從模型的角度來看,hadoop mapreduce 是比較粗糙的,無論什麼方法都只能用 map reduce 的方式來執行,而這種方式無疑不是萬能的,很多應用場景都很難解決。而從做資料庫的角度來看,這無非也就是乙個 select + groupby() 。這也就是為什麼有了後面 spark 基於 dag 的 rdd 概念的崛起。

這裡不得不多說一句,hadoop 的檔案系統 hadoop hdfs 才是 hadoop mapreduce 的基礎,因為 map reduce 最實質的支撐其實就是這個 hadoop hdfs 。沒有它, map reduce 不過是空中閣樓。你看,在 hadoop mapreduce 式微的今天,hadoop hdfs 還不是活得好好的,spark 或是 hive 這些工具也都是以它為基礎。不得不說,hadoop hdfs 才牛逼啊。

好了,接下來我們來**一下為什麼會出現 hadoop mapreduce 這個東西。

mapreduce 在 google 最大的應用是做網頁的索引。大家都知道 google 是做搜尋引擎起家的,而搜尋引擎的基本原理就是索引,就是爬去網際網路上的網頁,然後對建立單詞->文件的索引。這樣什麼搜尋關鍵字,才能找出對應網頁。這也是為什麼 google 會以 wordcount 作為 mapreduce 的例子。

既然明白搜尋引擎的原理,那應該就明白自 2000 年來網際網路爆發的年代,單台機器肯定是不夠儲存大量的索引的,所以就有了分布式儲存,google 內部用的叫 gfs,hadoop hdfs 其實可以說是山寨 gfs 來的。而在 gfs 的基礎上,hadoop mapreduce 的出現也就自然而然了。

推薦閱讀:

大資料儲存的進化史 --從 raid 到 hdfs

從回溯演算法到分治界限演算法比較最大問題和最小問題

回溯法 分支界限 當採用佇列時,與回溯一樣,可以一定程度的剪掉一部分的解空間子樹。此時遍歷方式為廣度優先 當採用最優佇列時,可以最大程度的 剪掉 更可能多的解空間子樹,此事遍歷方式為廣度優先結合深度優先 原因 但是值得注意,由於其他層的父節點的上限大於各自的兒子節點和孫子節點等的上限,所以只要最底下...

從模型到演算法 目錄

出於對資料分析 資料探勘方面的興趣,以及在未來工作上的幫助。本博打算多看一些相關書籍與部落格,總結及翻譯相應的知識點。使得自己對這塊的知識越來越了解,總結的文章初步分為以下章節 第一章,eda 資料探索 第二章,線性回歸與模型診斷 第三章,從線性概率模型到廣義線性模型 第四章,模型中特徵子集的選擇 ...

從合併排序演算法看「分治法」

分治法 divide and conquer 分治法策略 是一種很重要的演算法。顧名思義,分而治之 將原問題劃分成n個規模較小,而結構與原問題相似的子問題 遞迴地解決這些子問題,然後再合併其結果,就得到原問題的解。分治策略 是很多高效演算法的基礎,如快速排序 歸併排序 傅利葉變換 快速傅利葉變換 備...