分布式离线计算—MapReduce—基础介绍
原文作者:哪有天生的學霸,一切都是厚積薄發
原文地址:MapReduce介紹
目錄
場景
MapReduce產生背景
MapReduce功能:
總結
場景
比如有海量的文本文件,如訂單,頁面點擊事件的記錄,量特別大,單機版很難搞定,怎么解決海量數據的計算?
求和: 1 + 5 +7 + 3 +4 +9 +3 + 5 +6
MapReduce產生背景
如果讓你統計日志里面的出現的某個URL的總次數,讓你自己去寫個單機版的程序,寫個邏輯:無非就是讀這個文件一行,然后把那個地方截取出來,截取出來之后,然后可以把它放到一個HashMap里面,用Map去重,看到一條新的URL ,就把它put進去,然后+1,如果下次看到再有就直接+1,沒有就put進去,單機版的話邏輯是很好實現,但是數據量一大,你覺得單機版本還能搞定嗎?
首先2T的文件,你放在單機上可能存不下來,如果再他多一點呢?比如幾千個文件,幾十個T,單機存都存不下,那么存在哪里-------hdfs上。因為放在HDFS上可以放很多很多,比如說HDFS上有100個節點,每個節點上能耐掛載8T的硬盤,那就有800T,800T,你每個文件存3個副本的話,你至少也能存100多個T文件,耗費了大概6個T的空間,但是你一旦放到HDFS上就有一個問題:你的文件就會被切散了,被切散到很多的機器上,這個時候,你再對它們進行統計,這個時候,按照原來的邏輯,會不會出現問題?
你的任何一個節點上存的是某個文件的某些塊,假設你是在那臺機器上去做統計的話,你統計到的永遠是局部的數據,那你專門寫一個客戶端,我的程序運行在這個客戶端上,我去讀數據,讀一點統計一點,到把整個文件都讀完了,統計結果也就出來了,問題是那樣的話,你的程序又變成了一個單機版的,那你的內存也就不夠,因為你要第一點進來統計一點,是不是要保存一些中間數據,那你可能內存也不夠了,而且你因為是一個單機版的程序,所以你的速度是不是也很慢,而且你還要不斷的從網絡里面去拿那些數據,也會很慢,所以這個時候呢?你專門寫一個客戶端去做統計,肯定是不合適。
那你是不是應該把你的程序分發到集群的每一臺DN上去做統計,也就是把運算往數據去移動,而不是把數據移動到運算,把我的運算邏輯移動到數據那端去,數據在哪里,我就在哪里運算,但是這也有一個問題,因為運算也變成了一個分布式的了,你的每一份運算結果都只是局部的結果,那么這個時候也存在問題:
你的代碼怎么實現分發到很多機器上去運行,這件事情誰幫你做,如果是要你自己寫程序的話,你是不是得有個U盤拷你的jar包,一個計算一個計算的去拷,拷完之后再啟動,每個機器都啟動jar,等你啟動最后一臺的時候,前面那臺已經運行完了,最后一臺才剛開始啟動,這個工作你用手動去做是不是不合適啊?所以當你把一個簡單的邏輯,變成這種分布式運行的時候,你發現很多問題就來了:
我的代碼怎么分發,怎么配置啟動環境,怎么啟動起來,這個是不是得有一個龐大的系統去做,也就是說你應該額外開發這么一個叫做資源分發和Java啟動程序這么一個配置 的系統,這個系統你會嗎?寫得出來嗎?你要是寫的話,是不是還得花很多時間,你還要寫很多東西,因為你現在的Java不一定是擅長那個領域的 ,那這個耗費的代價就很大了
那個數據,比如剛才那個日志數據,是放到HDFS上面去了,但是不代表HDFS上的每一臺DN上面都有這一部分數據里面的內容,因為我們這個集群很大,你這個文件存進去的時候可能只占了其中的30臺節點,其中某30臺節點上有你這些文件,其他節點上個根本就沒有你這些文件,那我們的代碼,運行邏輯,最好是放到那30臺上面去做統計,你放到其他的那些機器上,它可以運行,但是它的數據必須來源于網絡,是不是效率會比較低,也就是說你的代碼究竟分發到哪些機器上去運行,是不是也要一個策略的問題,那么這個策略是不是也有一定的算法,那么這個時候,你為了實現你那個簡單的邏輯,就再去開發這樣一個系統出來是不是也是很大的開發量,再考慮一個問題,假如剛才那兩個工作你都做完了,你的代碼真的成功的在那30臺機器上跑起來了,跑起來之后,其中假設有一臺機器宕機了,那么你統計的那一部分局部數據是不是也就沒有了,那個局部結果也就沒有了,那個局部結果沒有,假設你有個匯總的結果還正確嗎?沒有意義了,也就是說你還得解決一個問題,就是你時時刻刻得卻監控著你的程序運行情況,那個節點正常,哪個節點不正常,這個問題也是很復雜的,假設這個問題 你也解決了,還有一個問題:
剛才你的邏輯只是統計出中間結果,這個時候是不是還得匯總啊,匯總就是意味著,你要在那30臺節點之間結果里面才能匯總,要么把它們全部調到一臺機器上就能進行匯總,但是你調到一臺機器上匯總的話,你那一臺機器的負載是不是會很高,對吧?假設我調到多態機器匯總,邏輯就變得復雜了,比如說,只要是你們那30臺機器上統計,每臺機器上的那個URL有多少條,你又把那個所有那個URL的數據全部匯總到某個匯總節點,假如有兩個URL,哪個URL分發到那個節點上進行匯總,這個策略是不是也會變得很復雜了,那你還得去做個中間數據的調度系統,那也很麻煩。
那這樣的話,我們就發現,哪怕是一個很簡單的東西,你也要把它變成一個分布式運行的程序,是不是面臨很多很多其他的問題,跟我們邏輯無關的問題,往往這些問題要比解決那個邏輯要復雜得多,那么這些問題解決不是我們擅長的,我們大量的普通程序員還沒達到那些程度,這么復雜的問題要寫出來是不是很麻煩呢?你不能要求每個程序員都能達到那個功力把,我們不過就是寫個簡單的邏輯統計這個文本里面哪個URL出現的總次數,很簡單的東西,所以呢,MapReduce才是我們這些普通程序員的福音。
就是說當我們面臨海量數據處理的時候,那個邏輯也許很簡單,但是面臨海量數據處理,要我們這個 邏輯代碼變成分布式運行,就會變得很復雜,而那些很復雜的事情又不是我們關心的,我關心的只是那個邏輯,那這個時候,就有人把你不擅長的而且又必須解決的,而且跟你的邏輯關系又不大的那些東西全部給封裝起來,那么這個時候,我們是不是就直接寫邏輯了,就會MapReduce的框架和Yarn,這兩個是不是做運算的,由這兩個框架把我們剛才講的那些東西全部封裝起來,這個就是MapReduce產生的背景,就是這個問題。
MapReduce功能:
綜上,MapReduce提供了以下的主要
- 數據劃分和計算任務調度:
系統自動將一個作業(Job)待處理的大數據劃分為很多個數據塊,每個數據塊對應于一個計算任務(Task),并自動 調度計算節點來處理相應的數據塊。作業和任務調度功能主要負責分配和調度計算節點(Map節點或Reduce節點),同時負責監控這些節點的執行狀態,并 負責Map節點執行的同步控制。
- 數據/代碼互定位:
為了減少數據通信,一個基本原則是本地化數據處理,即一個計算節點盡可能處理其本地磁盤上所分布存儲的數據,這實現了代碼向 數據的遷移;當無法進行這種本地化數據處理時,再尋找其他可用節點并將數據從網絡上傳送給該節點(數據向代碼遷移),但將盡可能從數據所在的本地機架上尋 找可用節點以減少通信延遲。
- 系統優化:
為了減少數據通信開銷,中間結果數據進入Reduce節點前會進行一定的合并處理;一個Reduce節點所處理的數據可能會來自多個 Map節點,為了避免Reduce計算階段發生數據相關性,Map節點輸出的中間結果需使用一定的策略進行適當的劃分處理,保證相關性數據發送到同一個 Reduce節點;此外,系統還進行一些計算性能優化處理,如對最慢的計算任務采用多備份執行、選最快完成者作為結果。
- 出錯檢測和恢復:
以低端商用服務器構成的大規模MapReduce計算集群中,節點硬件(主機、磁盤、內存等)出錯和軟件出錯是常態,因此 MapReduce需要能檢測并隔離出錯節點,并調度分配新的節點接管出錯節點的計算任務。同時,系統還將維護數據存儲的可靠性,用多備份冗余存儲機制提 高數據存儲的可靠性,并能及時檢測和恢復出錯的數據。
總結
把我們很簡單的運算邏輯很方便的擴展到海量數據的場景下分布式運算,所以MapReduce程序對我們程序員來說很簡單,因為它把那些東西都給封裝起來了,你只要寫業務邏輯,寫業務邏輯還不擅長嗎?業務邏輯大部分就是處理文本,處理字符串,我們學的大部分邏輯里面,大部分都是在處理這個問題:處理文本、處理字符串、查詢數據庫是不是得到一些東西啊。查詢一下數據庫,處理一下字符串,輸出結果,而這個邏輯本身 不用你太多的分布式細節 ,你只要把邏輯寫出來就可以了,但是你寫MapReduce的時候,必須要符合人家編程的規范,你不能你的寫法寫,他按他的寫法寫,每個人的寫法都不一樣,那MapReduce也沒法給你去分發和運行,所以你也要符合他的規范,怎樣才算符合規范呢?就說你的代碼,你的任意一個邏輯實現都要分成這么兩個步驟:
比如說我們統計日志文件里面,相同URL出現的總次數如下圖:
例子:
?
總結
以上是生活随笔為你收集整理的分布式离线计算—MapReduce—基础介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 常见索引结构—FST
- 下一篇: 分布式离线计算—MapReduce—为什
