課程地址:MapReduce
官方文檔:MapReduce Tutorial
參考文獻:MapReduce原理與設計思想
目錄
0、什么樣的計算任務可進行并行化計算?
1、MapReduce的原理
2、MapReduce運行原理
3、上升到構架-自動并行化并隱藏低層細節
4、MapReduce的主要設計思想和特征
0、什么樣的計算任務可進行并行化計算?
并行計算的第一個重要問題是如何劃分計算任務或者計算數據以便對劃分的子任務或數據塊同時進行計算。但一些計算問題恰恰無法進行這樣的劃分!
例如:Fibonacci函數: Fk+2 = Fk + Fk+1
前后數據項之間存在很強的依賴關系,只能串行計算!
結論:不可分拆的計算任務或相互間有依賴關系的數據無法進行并行計算!
大數據的并行化計算
一個大數據若可以分為具有同樣計算過程的數據塊,并且這些數據塊之間不存在數據依賴關系,則提高處理速度的最好辦法就是并行計算。
例如:假設有一個巨大的2維數據需要處理(比如求每個元素的開立方),其中對每個元素的處理是相同的,并且數據元素間不存在數據依賴關系,可以考慮不同的劃分方法將其劃分為子數組,由一組處理器并行處理。
1、MapReduce的原理:通過分散計算來分析大量數據
- 分:Map(大任務分成子任務)
- 治:Reduce(合并結果)
MapReduce合并了兩種經典函數:
- 映射(Mapping):對集合里的每個目標應用同一個操作。
- 化簡(Reducing ):遍歷集合中的元素來返回一個綜合的結果。
*Input Split(輸入分割) -> Map Task(各自統計) -> Shuffle(統計結果交換、規約) -> Reduce Task(統計合并結果) -> Output *
上升到抽象模型:Mapper與Reducer
MPI等并行計算方法缺少高層并行編程模型,為了克服這一缺陷,MapReduce借鑒了Lisp函數式語言中的思想,用Map和Reduce兩個函數提供了高層的并行編程抽象模型
上升到構架:統一構架,為程序員隱藏系統層細節
MPI等并行計算方法缺少統一的計算框架支持,程序員需要考慮數據存儲、劃分、分發、結果收集、錯誤恢復等諸多細節;為此,MapReduce設計并提供了統一的計算框架,為程序員隱藏了絕大多數系統層面的處理細節
關鍵思想:為大數據處理過程中的兩個主要處理操作提供一種抽象機制
MapReduce借鑒了函數式程序設計語言Lisp中的思想,定義了如下的Map和Reduce兩個抽象的編程接口,由用戶去編程實現:
- map: (k1; v1) → [(k2; v2)]
輸入:鍵值對(k1; v1)表示的數據
處理:文檔數據記錄(如文本文件中的行,或數據表格中的行)將以“鍵值對”形式傳入map函數;map函數將處理這些鍵值對,并以另一種鍵值對形式輸出處理的一組鍵值對中間結果[(k2; v2)]
輸出:鍵值對[(k2; v2)]表示的一組中間數據
- reduce: (k2; [v2]) → [(k3; v3)]
輸入: 由map輸出的一組鍵值對[(k2; v2)] 將被進行合并處理將同樣主鍵下的不同數值合并到一個列表[v2]中,故reduce的輸入為(k2; [v2])
處理:對傳入的中間結果列表數據進行某種整理或進一步的處理,并產生最終的某種形式的結果輸出[(k3; v3)] 。
輸出:最終輸出結果[(k3; v3)]
- 各個map函數對所劃分的數據并行處理,從不同的輸入數據產生不同的中間結果輸出
- 各個reduce也各自并行計算,各自負責處理不同的中間結果數據集合?進行reduce處理之前,必須等到所有的map函數做完,因此,在進入reduce前需要有一個同步障(barrier);這個階段也負責對map的中間結果數據進行收集整理(aggregation & shuffle)處理,以便reduce更有效地計算最終結
- 最終匯總所有reduce的輸出結果即可獲得最終結果
2、MapReduce運行原理
Job / Task / Tracker
-
Job:作業,一個計算任務
Task:一個作業拆分成多個task,分為MapTask和ReduceTask
- 兩類結點:
JobTracker:master管理節點;客戶端提交jobs,將job排到候選隊列;對要處理的job拆分成MapTask,并分發給各個節點上的Map TaskTracker來做。
作用是:(1)作業調度;(2)分配任務給具體的TaskTracker、監控TaskTracker的執行進度;(3)監控TaskTracker的狀態。
TaskTracker:負責具體執行計算任務,通常和要處理的DataNode處于同一個節點,這樣保證計算是跟著數據走的——“移動計算代替移動數據”;向JobTracker匯報任務狀態。
MapReduce作業執行過程
(1)輸入數據、分片;
(2)按照一定規則將分片的數據分給Map端的TaskTracker,分配map任務;
(3)map產生的中間結果:key-value對(中間結果寫入到本地磁盤),根據映射規則進行交換;
(4)將中間結果傳送到Reduce端的TaskTracker,執行Reduce任務;
(5)將最終計算結果寫回HDFS;
- 所有任務都由JobTracker進行分配(Map任務 / Reduce任務)
MapReduce的容錯機制
允許TaskTracker出錯、發生故障,但保證高可用性
- (1)重復執行:默認可重復執行4次
- (2)推測執行:正常情況下,所有map任務執行完成后Reduce才開始執行,如果中間發現某個TaskTracker計算非常慢,推測執行將會:算的慢的TaskTracker A繼續計算,另外在啟動一個TaskTracker B執行與A相同的task,最后以A、B中先計算完成的為準。
3、上升到構架-自動并行化并隱藏低層細節
如何提供統一的計算框架
MapReduce提供一個統一的計算框架,可完成:
- 計算任務的劃分和調度
- 數據的分布存儲和劃分
- 處理數據與計算任務的同步
- 結果數據的收集整理(sorting, combining, partitioning,…)
- 系統通信、負載平衡、計算性能優化處理
- 處理系統節點出錯檢測和失效恢復
MapReduce最大的亮點:
- 通過抽象模型和計算框架把需要做什么(what need to do)與具體怎么做(how to do)分開了,為程序員提供一個抽象和高層的編程接口和框架
- 程序員僅需要關心其應用層的具體計算問題,僅需編寫少量的處理應用本身計算問題的程序代碼
- 如何具體完成這個并行計算任務所相關的諸多系統層細節被隱藏起來,交給計算框架去處理:從分布代碼的執行,到大到數千小到單個節點集群的自動調度使用
MapReduce提供的主要功能
任務調度:提交的一個計算作業(job)將被劃分為很多個計算任務(tasks), 任務調度功能主要負責為這些劃分后的計算任務分配和調度計算節點(map節點或reducer節點); 同時負責監控這些節點的執行狀態, 并負責map節點執行的同步控制(barrier); 也負責進行一些計算性能優化處理, 如對最慢的計算任務采用多備份執行、選最快完成者作為結果
數據/代碼互定位:為了減少數據通信,一個基本原則是本地化數據處理(locality),即一個計算節點盡可能處理其本地磁盤上所分布存儲的數據,這實現了代碼向數據的遷移;當無法進行這種本地化數據處理時,再尋找其它可用節點并將數據從網絡上傳送給該節點(數據向代碼遷移),但將盡可能從數據所在的本地機架上尋找可用節點以減少通信延遲
出錯處理:以低端商用服務器構成的大規模MapReduce計算集群中,節點硬件(主機、磁盤、內存等)出錯和軟件有bug是常態,因此,MapReducer需要能檢測并隔離出錯節點,并調度分配新的節點接管出錯節點的計算任務
分布式數據存儲與文件管理:海量數據處理需要一個良好的分布數據存儲和文件管理系統支撐,該文件系統能夠把海量數據分布存儲在各個節點的本地磁盤上,但保持整個數據在邏輯上成為一個完整的數據文件;為了提供數據存儲容錯機制,該文件系統還要提供數據塊的多備份存儲管理能力
Combiner和Partitioner:為了減少數據通信開銷,中間結果數據進入reduce節點前需要進行合并(combine)處理,把具有同樣主鍵的數據合并到一起避免重復傳送; 一個reducer節點所處理的數據可能會來自多個map節點, 因此, map節點輸出的中間結果需使用一定的策略進行適當的劃分(partitioner)處理,保證相關數據發送到同一個reducer節點
4、MapReduce的主要設計思想和特征
(1)向“外”橫向擴展,而非向“上”縱向擴展(Scale “out", not “up”)
即MapReduce集群的構筑選用價格便宜、易于擴展的大量低端商用服務器,而非價格昂貴、不易擴展的高端服務器(SMP)。低端服務器市場與高容量Desktop PC有重疊的市場,因此,由于相互間價格的競爭、可互換的部件、和規模經濟效應,使得低端服務器保持較低的價格。基于TPC-C在2007年底的性能評估結果,一個低端服務器平臺與高端的共享存儲器結構的服務器平臺相比,其性價比大約要高4倍;如果把外存價格除外,低端服務器性價比大約提高12倍。對于大規模數據處理,由于有大量數據存儲需要,顯而易見,基于低端服務器的集群遠比基于高端服務器的集群優越,這就是為什么MapReduce并行計算集群會基于低端服務器實現。
(2)失效被認為是常態(Assume failures are common)
MapReduce集群中使用大量的低端服務器(Google目前在全球共使用百萬臺以上的服務器節點),因此,節點硬件失效和軟件出錯是常態,因而:一個良好設計、具有容錯性的并行計算系統不能因為節點失效而影響計算服務的質量,任何節點失效都不應當導致結果的不一致或不確定性;任何一個節點失效時,其它節點要能夠無縫接管失效節點的計算任務;當失效節點恢復后應能自動無縫加入集群,而不需要管理員人工進行系統配置。MapReduce并行計算軟件框架使用了多種有效的機制,如節點自動重啟技術,使集群和計算框架具有對付節點失效的健壯性,能有效處理失效節點的檢測和恢復。
(3)把處理向數據遷移(Moving processing to the data)
傳統高性能計算系統通常有很多處理器節點與一些外存儲器節點相連,如用區域存儲網絡(SAN,Storage Area Network)連接的磁盤陣列,因此,大規模數據處理時外存文件數據I/O訪問會成為一個制約系統性能的瓶頸。為了減少大規模數據并行計算系統中的數據通信開銷,代之以把數據傳送到處理節點(數據向處理器或代碼遷移),應當考慮將處理向數據靠攏和遷移。MapReduce采用了數據/代碼互定位的技術方法,計算節點將首先將盡量負責計算其本地存儲的數據,以發揮數據本地化特點(locality),僅當節點無法處理本地數據時,再采用就近原則尋找其它可用計算節點,并把數據傳送到該可用計算節點。
(4)順序處理數據、避免隨機訪問數據(Process data sequentially and avoid random access)
大規模數據處理的特點決定了大量的數據記錄不可能存放在內存、而只可能放在外存中進行處理。磁盤的順序訪問和隨即訪問在性能上有巨大的差異。
例:100億(1010)個數據記錄(每記錄100B,共計1TB)的數據庫,更新1%的記錄(一定是隨機訪問)需要1個月時間;而順序訪問并重寫所有數據記錄僅需1天時間!
MapReduce設計為面向大數據集批處理的并行計算系統,所有計算都被組織成很長的流式操作,以便能利用分布在集群中大量節點上磁盤集合的高傳輸帶寬。
(5)為應用開發者隱藏系統層細節(Hide system-level details from the application developer)
軟件工程實踐指南中,專業程序員認為之所以寫程序困難,是因為程序員需要記住太多的編程細節(從變量名到復雜算法的邊界情況處理),這對大腦記憶是一個巨大的認知負擔,需要高度集中注意力。而并行程序編寫有更多困難,如需要考慮多線程中諸如同步等復雜繁瑣的細節,由于并發執行中的不可預測性,程序的調試查錯也十分困難;大規模數據處理時程序員需要考慮諸如數據分布存儲管理、數據分發、數據通信和同步、計算結果收集等諸多細節問題。MapReduce提供了一種抽象機制將程序員與系統層細節隔離開來,程序員僅需描述需要計算什么(what to compute), 而具體怎么去做(how to compute)就交由系統的執行框架處理,這樣程序員可從系統層細節中解放出來,而致力于其應用本身計算問題的算法設計。
(6)平滑無縫的可擴展性(Seamless scalability)
主要包括兩層意義上的擴展性:數據擴展和系統規模擴展。理想的軟件算法應當能隨著數據規模的擴大而表現出持續的有效性,性能上的下降程度應與數據規模擴大的倍數相當。在集群規模上,要求算法的計算性能應能隨著節點數的增加保持接近線性程度的增長。絕大多數現有的單機算法都達不到以上理想的要求;把中間結果數據維護在內存中的單機算法在大規模數據處理時很快失效;從單機到基于大規模集群的并行計算從根本上需要完全不同的算法設計。奇妙的是,MapReduce幾乎能實現以上理想的擴展性特征。 多項研究發現基于MapReduce的計算性能可隨節點數目增長保持近似于線性的增長。