1. 程式人生 > >anhuidelinger的專欄

anhuidelinger的專欄

摘要

MapReduce是一個程式設計模式,它是與處理/產生海量資料集的實現相關。使用者指定一個map函式,通過這個map函式處理key/value(鍵/值)對,並且產生一系列的中間key/value對,並且使用reduce函式來合併所有的具有相同key值的中間鍵值對中的值部分。現實生活中的很多工的實現都是基於這個模式的,正如本文稍後會講述的那樣。

使用這樣的函式形式實現的程式可以自動分佈到一個由普通機器組成的超大幾群上併發執行。run-time系統會解決輸入資料的分佈細節,跨越機器叢集的程式執行排程,處理機器的失效,並且管理機器之間的通訊請求。這樣的模式允許程式設計師可以不需要有什麼併發處理或者分散式系統的經驗,就可以處理超大的分散式系統得資源。

我們的MapReduce系統的實現執行在一個由普通機器組成的大型叢集上,並且有著很高的擴充套件性:一個典型的MapReduce計算處理通常分佈到上千臺機器上來處理上TB的資料。程式設計師會發現這樣的系統很容易使用:已經開發出來了上百個MapReduce程式,並且每天在Google的叢集上有上千個MapReduce job正在執行。

1 介紹

在過去的5年內,Google的創造者和其他人實現了上百個用於特別計算目的的程式來出來海量的原始資料,比如蠕蟲文件,web請求log,等等,用於計算出不同的資料,比如降序索引,不同的圖示展示的web文件,蠕蟲採集的每個host的page數量摘要,給定日期內最常用的查詢等等。絕大部分計算都是概念上很簡潔的。不過,輸入的資料通常是非常巨大的,並且為了能在合理時間內執行完畢,其上的計算必須分佈到上百個或者上千個計算機上去執行。如何併發計算,如何分佈資料,如何處理失敗等等相關問題合併在一起就會導致原本簡單的計算掩埋在為了解決這些問題而引入的很複雜的程式碼中。

因為這種複雜度,我們設計了一種新的東西來讓我們能夠方便處理這樣的簡單計算。這些簡單計算原本很簡單,但是由於考慮到併發處理細節,容錯細節,以及資料分佈細節,負載均衡等等細節問題,而導致程式碼非常複雜。所以我們抽象這些公共的細節到一個lib中。這種抽象是源自Lisp以及其他很多面向功能的語言的map和reduce概念。我們認識到大部分操作都和map操作相關,這些map操作都是運算在輸入記錄的每個邏輯”record”上,並且map操作為了產生一組中間的key/value鍵值對,並且接著在所有相同key的中間結果上執行reduce操作,這樣就可以合併適當的資料。我們得函式模式是使用使用者定義的map和reduce操作,這樣可以讓我們併發執行大規模的運算,並且使用重新執行的方式作為容錯的優先機制。

MapReduce的主要貢獻在於提供了一個簡單強大的介面,通過這個介面,可以把大尺度的計算自動的併發和分佈執行。使用這個介面,可以通過普通PC的巨大叢集,來達到極高的效能。

第二節講述了基本的程式設計模式,並且給出了一些例子。第三節講述了一個面向我們基於叢集的計算環境的MapReduce的實現。第四節講述了一些我們建議的精巧程式設計模式。第五節講述了在不同任務下我們的MapReduce實現的效能比較。第六節講述了在Google中的MapReduce應用以及嘗試重寫了我們產品的索引系統。第七節講述了相關工作和未來的工作。

2 程式設計模式

我們的運算處理一組輸入的(input)鍵值對(key/valuepairs),並且產生一組輸出的(output)鍵值對。MapReduce函式庫德使用者用兩個函式來表達這樣的計算:Map和Reduce。

Map函式,是使用者自定義的的函式,處理輸入的鍵值對,並且產生一組中間的(intermediate)鍵值對。MapReduce函式庫稽核所有相同的中間鍵值鍵I的值,並且傳送給Reduce函式進行處理。

Reduce函式同樣也是使用者提供的,它處理中間鍵值I,以及這個中間鍵值相關的值集合。這個函式合併這些值,最後形成一個相對較小的值集合。通常一個單次Reduce執行會產生0個或者1個輸出值。提供給Reduce函式的中間值是通過一個iterator來提供的。這就讓我們可以處理超過記憶體容量的值列表。

2.1 例子

我們考慮這樣一個例子,在很大的文件集合中統計每一個單詞出現的次數。我們寫出類似如下的虛擬碼:

map(String key, String value):

       // key: document name

       // value: document contents

       for each word w in value:

              EmitIntermediate(w, “1″);

reduce(String key, Iterator values):

       // key: a word

       // values: a list of counts

       int result = 0;

       for each v in values:

              result += ParseInt(v);

       Emit(AsString(result));

map函式檢查每一個單詞,並且對每一個單詞增加1到其對應的計數器(在這個例子裡就是’1’).reduce函式把特定單詞的所有出現的次數進行合併。

此外,我們還要寫程式碼來對mapreduce specification物件進行賦值,設定輸入和輸出的檔名,以及設定一些引數。接著我們呼叫MapReduce函式,把這個物件作為引數呼叫過去。我們把MapReduce函式庫(C++函式庫)和我們的程式連結在一起。附件1有完整的這個例子的程式碼。

2.2 型別

即使上邊的例子是用字串作為輸入和輸入出的,從概念上講,使用者提供的map和reduce函式有著如下相關型別:

map (k1,v1)                à    list(k2,v2)

reduce (k2,list(v2))             à    list(v2)

也就是,輸入的鍵和值和輸出的鍵值是屬於不同的域的。進一步說,中間的鍵值是和輸出的鍵值屬於相同的域的。(比如map的輸出,就是作為reduce的輸入)。

我們的C++實現上,把字串作為使用者定義函式的輸入和輸出,由使用者程式碼來自己識別字符串到合適的型別。

2.3 其他例子

這裡有一些簡單有趣的例子,都可以簡單的通過MapReduce計算模型來展示:

分散式Grep:            如果map函式檢查輸入行,滿足條件的時候,map函式就把本行輸出。reduce函式就是一個直通函式,簡單的把中間資料輸出就可以了。

URL訪問頻率統計:  map函式處理webpag請求和應答(URL,1)的log。Reduce函式把所有相同的URL的值合併,並且輸出一個成對的(URL,總個數)。

逆向Web-Link 圖:   map函式輸出所有包含指向target URL的source網頁,用(target,source)這樣的結構對輸出。Reduce函式局和所有關聯相同target URL的source列表,並且輸出一個(target,list(source))這樣的結構。

主機關鍵向量指標(Term-Vector per Hosts):   關鍵詞向量指標簡而言之就是在一個文件或者一組文件中的重點次出現的頻率,用(word,frequency)表達。map函式計算每一個輸入文件(主機名字是從文件的URL取出的)的關鍵詞向量,然後輸出(hostname,關鍵詞向量(Term-Vector))。reduce函式處理所有相同host的所有文件關鍵詞向量。去掉不常用的關鍵詞,並且輸出最終的(hostname,關鍵詞向量)對。

逆序索引:                 map函式分析每一個文件,並且產生一個序列(word,documentID)組。reduce函式處理指定word的所有的序列組,並且對相關的document ID進行排序,輸出一個(word,list(document ID))組。所有的輸出組,組成一個簡單的逆序索引。通過這種方法可以很容易保持關鍵詞在文件庫中的位置。

分散式排序:                    map函式從每條記錄中抽取關鍵字,並且產生(key,record)對。reduce函式原樣輸出所有的關鍵字對。這個演算法是與4.1節描述的分散式處理相關的,並且排序是在4.2節描述的。

3 實現

MapReduce介面可以有很多種不同的實現。應當根據不同的環境選擇不同的實現。比如,一個實現可以適用於小型的共享記憶體的機器,另一個實現可能是基於大型NUMA多處理器系統,還可能有為大規模計算機叢集的實現。

本屆描述了Google廣泛使用的計算環境:用交換機網路[4]連線的,由普通PC構成的超大叢集。在我們的環境裡:

(1)     每個節點通常是雙x86處理器,執行Linux,每臺機器2-4GB記憶體。

(2)     使用的網路裝置都是常用的。一般在節點上使用的是100M/或者千M網路,一般情況下都用不到一半的網路頻寬。

(3)     一個cluster中常常有成百上千臺機器,所以,機器故障是家常便飯。

(4)     儲存時使用的便宜的IDE硬碟,直接放在每一個機器上。並且有一個分散式的檔案系統來管理這些分佈在各個機器上的硬碟。檔案系統通過複製的方法來在不可靠的硬體上保證可用性和可靠性。

(5)     使用者向排程系統提交請求。每一個請求都包含一組任務,對映到這個計算機cluster裡的一組機器上執行。

3.1 執行概覽

Map操作通過把輸入資料進行分割槽(partition)(比如分為M塊),就可以分佈到不同的機器上執行了。輸入塊的拆成多塊,可以並行在不同機器上執行。Reduce操作是通過對中間產生的key的分佈來進行分佈的,中間產生的key可以根據某種分割槽函式進行分佈(比如hash(key) mod R),分佈成為R塊。分割槽(R)的數量和分割槽函式都是由使用者指定的。

圖1是我們實現的MapReduce操作的整體資料流。當用戶程式呼叫MapReduce函式,就會引起如下的操作(圖一中的數字標示和下表的數字標示相同)。

1. 使用者程式中的MapReduce函式庫首先把輸入檔案分成M塊,每塊大概16M到64M(可以通過引數決定)。接著在cluster的機器上執行處理程式。

2. 這些分排的執行程式中有一個程式比較特別,它是主控程式master。剩下的執行程式都是作為master分排工作的worker。總共有M個map任務和R個reduce任務需要分排。master選擇空閒的worker並且分配這些map任務或者reduce任務

3. 一個分配了map任務的worker讀取並處理相關的輸入小塊。他處理輸入的資料,並且將分析出的key/value對傳遞給使用者定義的map函式。map函式產生的中間結果key/value對暫時緩衝到記憶體。

4. 這些緩衝到記憶體的中間結果將被定時刷寫到本地硬碟,這些資料通過分割槽函式分成R個區。這些中間結果在本地硬碟的位置資訊將被髮送回master,然後這個master負責把這些位置資訊傳送給reduce的worker。

5. 當master通知reduce的worker關於中間key/value對的位置時,他呼叫remote procedure來從map worker的本地硬碟上讀取緩衝的中間資料。當reduce的worker讀到了所有的中間資料,他就使用中間key進行排序,這樣可以使得相同key的值都在一起。因為有許多不同key的map都對應相同的reduce任務,所以,排序是必須的。如果中間結果集太大了,那麼就需要使用外排序。

6. reduce worker根據每一個唯一中間key來遍歷所有的排序後的中間資料,並且把key和相關的中間結果值集合傳遞給使用者定義的reduce函式。reduce函式的對於本reduce區塊的輸出到一個最終的輸出檔案。

7. 當所有的map任務和reduce任務都已經完成了的時候,master啟用使用者程式。在這時候MapReduce返回使用者程式的呼叫點。

當這些成功結束以後,mapreduce的執行資料存放在總計R個輸出檔案中(每個都是由reduce任務產生的,這些檔名是使用者指定的)。通常,使用者不需要合併這R個輸出檔案到一個檔案,他們通常把這些檔案作為輸入傳遞到另一個MapReduce呼叫,或者用另一個分散式應用來處理這些檔案,並且這些分散式應用把這些檔案看成為輸入檔案由於分割槽(partition)成為的多個塊檔案。

3.2 Master的資料結構

master需要儲存一定的資料結構。對於每一個map和reduce任務來說,都需要儲存它的狀態(idle,in-progress或者completed),並且識別不同的worker機器(對於非idel的任務狀態)。

master是一個由map任務產生的中間區域檔案位置資訊到reduce任務的一個管道。因此,對於每一個完成得map任務,master儲存下來這個map任務產生的R中間區域檔案資訊的位置和大小。對於這個位置和大小資訊是當接收到map任務完成得時候做的。這些資訊是增量推送到處於in-progress狀態的reduce任務的worker上的。

3.3 容錯考慮

由於MapReduce函式庫是設計用於在成百上千臺機器上處理海量資料的,所以這個函式庫必須考慮到機器故障的容錯處理。

Worker失效的考慮

master會定期ping每一個worker機器。如果在一定時間內沒有worker機器的返回,master就認為這個worker失效了。所有這臺worker完成的map任務都被設定成為他們的初始idel狀態,並且因此可以被其他worker所排程執行。類似的,所有這個機器上正在處理的map 任務或者reduce任務都被設定成為idle狀態,可以被其他worker所重新執行。

在失效機器上的已經完成的map任務還需要再次重新執行,這是因為中間結果存放在這個失效的機器上,所以導致中間結果無法訪問。已經完成的recude任務無需再次執行,因為他們的結果已經儲存在全域性的檔案系統中了。

當map任務首先由Aworker執行,隨後被Bworker執行的時候(因為A失效了),所有執行reduce任務的worker都會被通知。所有還沒有來得及從A上讀取資料的worker都會從B上讀取資料。

MapReduce可以有效地支援到很大尺度的worker失效的情況。比如,在一個MapReduce操作中,在一個網路例行維護中,可能會導致每次大約有80臺機器在幾分鐘之內不能訪問。MapReduce的master制式簡單的把這些不能訪問的worker上的工作再執行一次,並且繼續排程程序,最後完成MapReduce的操作。

Master失效

在master中,定期會設定checkpoint,寫出master的資料結構。如果master任務失效了,可以從上次最後一個checkpoint開始啟動另一個master程序。不過,由於只有一個master在執行,所以他如果失效就比較麻煩,因此我們當前的實現上,是如果master失效了,就終止MapReduce執行。客戶端可以檢測這種失效並且如果需要就重新嘗試MapReduce操作。

失效的處理設計

當用戶提供的map和reduce函式對於他們的輸入來說是確定性的函式,我們的分散式的輸出就應當和在一個整個程式沒有失敗的連續執行相同。

我們依靠對map和reduce任務的輸出進行原子提交來完成這樣的可靠性。每一個in-progress任務把輸出寫道一個私有的臨時檔案中。reduce任務產生一個這樣的檔案,map任務產生R個這樣的任務(每一個對應一個reduce任務)。當一個map任務完成的時候,worker傳送一個訊息給master,並且這個訊息中包含了這個R臨時檔案的名字。如果master又收到一個已經完成的map任務的完成訊息,他就忽略這個訊息。否則,他就在master資料結構中記錄這個R檔案。

當一個reduce任務完成的時候,reduce worker自動把臨時輸出的檔名改為正式的輸出檔案。如果再多臺機器上有相同的reduce任務執行,那麼就會有多個針對最終輸出檔案的更名動作。我們依靠檔案系統提供的原子操作’改名字’,來保證最終的檔案系統狀態中記錄的是其中一個reduce任務的輸出。

我們的絕大部分map和reduce操作都是確定性的,實際上在語義角度,這個map和reduce併發執行和順序執行市一樣的,這就使得程式設計師很容易推測程式行為。當map和reduce操作是非確定性的時候,我們有稍弱的但是依舊是有道理的錯誤處理機制。對於非確定性操作來說,特定reduce任務R1的輸出,與,非確定性的順序執行的程式對R1的輸出是等價的。另外,另一個reduce任務R2的輸出,是和另一個順序執行的非確定性程式對應的R2輸出相關的。

考慮map任務M和reduce任務R1,R2。我們設定e(Ri)為已經提交的Ri執行(有且僅有一個這樣的執行)。當e(R1)處理得是M的一次執行,而e(R2)是處理M的另一次執行的時候,那麼就會導致稍弱的失效處理了。

3.4 儲存位置

在我們的環境下,網路頻寬資源是相對缺乏的。我們用盡量讓輸入資料儲存在構成叢集機器的本地硬碟上(通過GFS管理[8])的方式來減少網路頻寬的開銷。GFS把檔案分成64M一塊,並且每一塊都有幾個拷貝(通常是3個拷貝),分佈到不同的機器上。MapReduce的master有輸入檔案組的位置資訊,並且嘗試分派map任務在對應包含了相關輸入資料塊的裝置上執行。如果不能分配map任務到對應其輸入資料的機器上執行,他就嘗試分配map任務到儘量靠近這個任務的輸入資料庫的機器上執行(比如,分配到一個和包含輸入資料塊在一個switch網段的worker機器上執行)。當在一個足夠大的cluster叢集上執行大型MapReduce操作的時候,大部分輸入資料都是在本地機器讀取的,他們消耗比較少的網路頻寬。

3.5 任務顆粒度

如果上邊我們講的,我們把map階段拆分到M小塊,並且reduce階段拆分到R小塊執行。在理想狀態下,M和R應當比worker機器數量要多得多。每一個worker機器都通過執行大量的任務來提高動態的負載均衡能力,並且能夠加快故障恢復的速度:這個失效機器上執行的大量map任務都可以分佈到所有其他worker機器上執行。

但是我們的實現中,實際上對於M和R的取值有一定的限制,因為master必須執行O(M+R)次排程,並且在記憶體中儲存O(M*R)個狀態。(對影響記憶體使用的因素還是比較小的:O(M*R)塊狀態,大概每對map任務/reduce任務1個位元組就可以了)

進一步來說,使用者通常會指定R的值,因為每一個reduce任務最終都是一個獨立的輸出檔案。在實際中,我們傾向於調整M的值,使得每一個獨立任務都是處理大約16M到64M的輸入資料(這樣,上面描寫的本地優化策略會最有效),另外,我們使R比較小,這樣使得R佔用不多的worker機器。我們通常會用這樣的比例來執行MapReduce: M=200,000,R=5,000,使用2,000臺worker機器。

3.6 備用任務

通常情況下,一個MapReduce的總執行時間會受到最後的幾個”拖後腿”的任務影響:在計算過程中,會有一個機器過了比正常執行時間長得多的時間還沒有執行完map或者reduce任務,導致MapReduce總任務不能按時完成。出現拖後腿的情況有很多原因。比如:一個機器的硬碟有點問題,經常需要反覆讀取糾錯,然後把讀取輸入資料的效能從30M/s降低到1M/s。cluster排程系統已經在某臺機器上排程了其他的任務,所以因為CPU/記憶體/本地硬碟/網路頻寬等競爭的關係,導致執行MapReduce的程式碼效能比較慢。我們最近出現的一個問題是機器的啟動程式碼有問題,導致關閉了cpu的cache:在這些機器上的任務效能有上百倍的影響。

我們有一個通用的機制來減少拖後腿的情況。當MapReduce操作接近完成的時候,master排程備用程序來執行那些剩下的in-progress狀態的任務。無論當最初的任務還是backup任務執行完成的時候,都把這個任務標記成為已經完成。我們調優了這個機制,通常只會佔用多幾個百分點的機器資源。但是我們發現這樣做以後對於減少超大MapReduce操作的總處理時間來說非常有效。例如,在5.3節描述的排序任務,在關閉掉備用任務的情況下,要比有備用任務的情況下多花44%的時間。

4 技巧

雖然簡單寫map和reduce函式實現基本功能就已經對大部分需要都足夠了,我們還是開發了一些有用的擴充套件,這些在本節詳細描述。

4.1 分割槽函式

MapReduce的使用者通過指定(R)來給出reduce 任務/輸出檔案的數量。他們處理的資料在這些任務上通過對中間結果key得分割槽函式來進行分割槽。預設的分割槽函式時使用hash函式(例如hash(key)mod R)。這一般就可以得到分散均勻的分割槽。不過,在某些情況下,對key用其他的函式進行分割槽可能更有用。比如,某些情況下key是URL,那麼我們希望所有對單個host的入口URL都儲存在相同的輸出檔案。為了支援類似的情況,MapReduce函式庫可以讓使用者提供一個特定的分割槽函式。比如使用hash(hostname(urlkey))mod R作為分割槽函式,這樣可以讓指向同一個hostname的URL分配到相同的輸出檔案中。

4.2 順序保證

我們確保在給定的分割槽中,中間鍵值對key/value的處理順序是根據key增量處理的。這樣的順序保證可以很容易生成每一個分割槽有序的輸出檔案,這對於輸出檔案格式需要支援客戶端的對key的隨機存取的時候就很有用,或者對輸出資料集再作排序就很容易。

4.3 combiner函式

在某些情況下,允許中間結果key重複會佔據相當的比重,並且使用者定義的reduce函式滿足結合律和交換律。比如2.1節的一個統計單詞出現次數的例子。由於word的頻率趨勢符合Zipf 分佈(齊夫分佈),每一個map任務都回產生成百上千的<the,1>這樣格式的記錄。所有這些記錄都通過網路傳送給一個單個的reduce任務,通過reduce函式進行相加,最後產生單個數字。我們允許使用者指定一個可選的組合函式Combiner函式,先在本地進行合併以下,然後再通過網路傳送。

Combiner函式在每一個map任務的機器上執行。通常這個combiner函式的程式碼和reduce的程式碼實現上都是一樣的。reduce函式和combiner函式唯一的不同就是MapReduce對於這兩個函式的輸出處理上不同。對於reduce函式的輸出是直接寫到最終的輸出檔案。對於combiner函式來說,輸出是寫到中間檔案,並且會被髮送到reduce任務中去。

部分使用combiner函式可以顯著提高某些型別的MapReduce操作。附錄A有這樣的使用combiner的例子。

4.4 輸入和輸出型別

MapReduce函式庫提供了讀取幾種不同格式的輸入的支援。例如,”text”模式下,每行輸入都被看成一個key/value對:key是在檔案的偏移量,value是行的內容。另一個寵用格式儲存了根據key進行排序key/value對的順序。每一個輸入型別的實現都知道如何把輸入為了分別得map任務而進行有效分隔(比如,text模式下的分隔就是要確保分隔的邊界只能按照行來進行分隔)。使用者可以通過簡單的提供reader介面來進行新的輸入型別的支援。不過大部分使用者都只用一小部分預先定義的輸入型別。

reader函式不需要提供從檔案讀取資料。例如,我們很容易定義一個reader函式從資料庫讀取資料,或者從儲存在記憶體中的資料結構中讀取資料。

類似的,我們提供了一組用於輸出的型別,可以產生不同格式的資料,並且使用者也可以很簡單的增加新的輸出型別。

4.5 邊界效應

在某些情況下,MapReduce的使用上,如果再map操作或者reduce操作時,增加輔助的輸出檔案,會比較有用。我們依靠程式來提供這樣的邊界原子操作。通常應用程式寫一個臨時檔案並且用系統的原子操作:改名字操作,來再這個檔案寫完的時候,一次把這個檔案改名改掉。

對於單個任務產生的多個輸出檔案來說,我們沒有提供其上的兩階段提交的原子操作支援。因此,對於產生多個輸出檔案的,對於跨檔案有一致性要求的任務,都必須是確定性的任務。這個限制到現在為止還沒有真正在實際中遇到過。

4.6 跳過損壞的記錄

某些情況下,使用者程式的程式碼會讓map或者reduce函式在處理某些記錄的時候crash掉。這種情況下MapReduce操作就不能完成。一般的做法是改掉bug然後再執行,但是有時候這種先改掉bug的方式不太可行;也許是因為bug是在第三方的lib裡邊,它的原始碼不存在等等。並且,很多時候,忽略一些記錄不處理也是可以接受的,比如,在一個大資料集上進行統計分析的時候,就可以忽略有問題的少量記錄。我們提供了一種執行模式,在這種執行模式下,MapReduce會檢測到哪些記錄會導致確定的crash,並且跳過這些記錄不處理,使得整個處理能繼續進行。

每一個worker處理程序都有一個signal handler,可以捕獲記憶體段異常和匯流排錯誤。在執行使用者map或者reduce操作之前,MapReduce函式庫通過全域性變數儲存記錄序號。如果使用者程式碼產生了這個訊號,signal handler於是用”最後一口氣”通過UDP包向master傳送上次處理的最後一條記錄的序號。當master看到在這個特定記錄上,有不止一個失效的時候,他就標誌著條記錄需要被跳過,,並且在下次重新執行相關的Map或者Reduce任務的時候跳過這條記錄。

4.7 本地執行

因為實際執行操作時分佈在系統中執行的,通常是在好幾千臺計算機上執行得,並且是由master機器進行動態排程的任務,所以對map和reduce函式的除錯就比較麻煩。為了能夠讓除錯方便,profiling和小規模測試,我們開發了一套MapReduce的本地實現,也就是說,MapReduce函式庫在本地機器上順序執行所有的MapReduce操作。使用者可以控制執行,這樣計算可以限制到特定的map任務上。使用者可以通過設定特別的標誌來執行他們的程式,同時也可以很容易的使用除錯和測試工具(比如gdb)等等。

4.8 狀態資訊

master內部有一個HTTP伺服器,並且可以輸出狀態報告。狀態頁提供了計算的進度報告,比如有多少任務已經完成,有多少任務正在處理,輸入的位元組數,中間資料的位元組數,輸出的位元組數,處理百分比,等等。這些頁面也包括了指向每個任務輸出的標準錯誤和輸出的標準檔案的連線。使用者可以根據這些資料來預測計算需要大約執行多長時間,是否需要為這個計算增加額外的計算資源。這些頁面也可以用來分析為何計算執行的會比預期的慢。

此外,最上層的狀態頁面也顯示了哪些worker失效了,以及他們失效的時候上面執行的map和reduce任務。這些資訊對於除錯使用者程式碼中的bug很有幫助。

4.9 計數器

MapReduce函式庫提供了用於統計不同事件發生次數的計數器。比如,使用者可能想統計所有已經索引的German文件數量或者已經處理了多少單詞的數量,等等。

為了使用這樣的特性,使用者程式碼建立一個叫做counter的物件,並且在map和reduce函式中在適當的時候增加counter的值。例如:

Counter* uppercase;

uppercase = GetCounter(“uppercase”);

map(String name, String contents):

       for each word w in contents:

              if (IsCapitalized(w)):

                     uppercase->Increment();

              EmitIntermediate(w, “1″);

這些counter的值,會定時從各個單獨的worker機器上傳遞給master(通過ping的應答包傳遞)。master把執行成功的map或者reduce任務的counter值進行累計,並且當MapReduce操作完成之後,返回給使用者程式碼。當前counter值也會顯示在master的狀態頁面,這樣人可以看到計算現場的進度。當累計counter的值的時候,master會檢查是否有對同一個map或者reduce任務的相同累計,避免累計重複。(backup任務或者機器失效導致的重新執行map任務或者reduce任務或導致這個counter重複執行,所以需要檢查,避免master進行重複統計)。

部分計數器的值是由MapReduce函式庫進行自動維持的,比如已經處理的輸入的key/value對的數量,或者輸出的key/value鍵值對等等。

counter特性對於MapReduce操作的完整性檢查非常有用。比如,在某些MapReduce操作中,使用者程式需要確保輸出的鍵值對精確的等於處理的輸入鍵值對,或者處理得German文件數量是在處理的整個文件數量中屬於合理範圍內。

5 效能

在本節,我們用在一個大型叢集上執行的兩個計算來衡量MapReduce的效能。一個計算用來在一個大概1TB的資料中查詢特定的匹配串。另一個計算排序大概1TB的資料。

相關推薦

anhuidelinger專欄

摘要 MapReduce是一個程式設計模式,它是與處理/產生海量資料集的實現相關。使用者指定一個map函式,通過這個map函式處理key/value(鍵/值)對,並且產生一系列的中間key/value對,並且使用reduce函式來合併所有的具有相同key值的中間

愛留圖 - 一個定期開設專欄活動的圖片收集網站誕生。

數據庫 解決方案 sql 本章和大家分享的是一個自制的圖片收集網站:愛留圖;本章不打算分享什麽技術知識點,而分享的主要內容有網站的創立的需求,現階段采用的技術架構,服務器配置等信息;在站點服務構建時用到的部分技術,知識點,以及遇到的問題會在後面分不同的章節+不同的小節來講解,樂於和大家分享自己的經

java執行程序的內存分析系列專欄

運行時 nbsp oid main 空間 如圖所示 jvm 性別 class 近段時間研究了java的程序執行過程中的內存分配,收獲頗多,解決了我最近時間學習java的很多困惑點。寫java內存分析系列的目的主要有兩個,一來是希望給像我一樣的java初學者

李開復華盛頓郵報專欄:發錢解決AI失業潮

2-2 都在 替代 客戶 人在 ews 狀況 職業 屬於 昨天,創新工場創始人兼 CEO 李開復博士在《華盛頓郵報》撰文稱,人工智能革命即將到來,這可能是一個最好的時代,也可能是最壞的時代。   好與壞,將取決於我們如何解決人工智能的副作用之一——失業問題。   根據牛津

【專家專欄】淺談百度搜索排序

百度搜索排序站長圈經常聊的話題中,怎麽提升百度排序一定是排名TOP3的問題,那百度排序的原理是什麽,該怎麽提升,今天給大家分享一下經驗心得。關於排序這件事兒對於像百度搜索來說,並沒有排序這一說法,搜索引擎認為排序是在特定的關鍵詞下網站內容的位置,而關鍵詞是由用戶搜索產生,如果一個關鍵詞沒有被搜索,也就意味著這

(轉載)【笨木頭Lua專欄】基礎補充20:面向對象——類和繼承

笑話 ava span 生成 code BE 手機 情況 忽略 終於來了,在Lua中的面向對象編程,相信目前學習Lua的大部分人都是為了開發手機網遊吧。而且基本都是奔著腳本語言的熱更新特性去的,所以全腳本開發變得十分流行。 對於普及不太廣的Lua(相對於C++、Java等主

(轉載)【笨木頭Lua專欄】基礎補充22:弱引用table

ive AC -c 所在 lan contain 函數 貢獻 缺陷 這次要介紹的內容比較少,就一個——弱引用table 笨木頭花心貢獻,哈?花心?不,是用心~ 轉載請註明,原文地址:http://www.benmutou.com/archives/1808 文章來源:

(轉載)【笨木頭Lua專欄】基礎補充21:面向對象——多重繼承、私密性

子類 先來 nta 參數 hive lua 封裝 完成 存在 在Lua中的多重繼承和私密性可能用得比較少,也可能只是我個人用得比較少。 本來想偷懶不寫這文章的,因為我今天剛買了個漂移板,連起步都還沒學會啊,想多學一會。 咳咳,本著堅持不懈、負責到底的態度,我還是決定隨便寫幾

SQLmap攻防實戰技術專欄開通

SQLmap攻防實戰技術專欄開通以前做專題研究,覺得專題研究才有意義,因為專題更加系統,更加科學,更加條理化,這次應51cto網站的邀請,準備了一個攻防實戰的專欄:滲透攻擊入門到實踐鏈接地址:http://blog.51cto.com/cloumn/detail/3目前該專欄已經正式上線,第一次做專欄,有些地

完成sqlmap滲透攻擊入門到實戰專欄文章初步目標

sqlmap滲透攻擊《滲透攻擊入門到實戰》專欄文章http://blog.51cto.com/cloumn/detail/3從推出到目前基本預訂目標17章內容完成更新。回顧整個過程有以下一些感受:1.技術的東西必須深入,目前安全圈安全生態不是特別好,很多內容都是copy,筆者在對某些內容進行查看時,根據文章提

【重大好消息】51CTO博客滲透攻擊專欄的陳小兵老師開直播啦~

博客專欄 專欄直播 直播課 【重大好消息】51CTO博客滲透攻擊專欄的陳小兵老師開直播啦~ 直播主題:SQLmap數據庫脫褲攻擊與防範 直播時間:2018年5月28日20:30-10:30 直播形式:(QQ群:430231379)群直播 點擊鏈接加入群聊【51CTO博客滲透專欄直播】

關於運維,你想知道的都在這兒了;運維專欄推薦及精選文章合集

運維 網絡運維 合集 推薦文章 博客專欄推薦:老司機網絡運維幹貨集錦(含路由交換安全Qos優化) 簡介:新西蘭某大型企業首席網絡設計師,負責全網的總體設計規劃,包含MPLS網絡總體規劃設計,數據中心規劃設計,全新西蘭分支機構WAN網絡和國際互聯網絡規劃設計等。 網絡運維,這是一個多坑的世

[算法專欄] 爬樓梯問題

窗口 dfs rst 狀態壓縮 ID 問題分析 復雜 else !=   題目:   一個臺階總共有n 級,如果一次可以跳1 級,也可以跳2 級,求總共有多少種跳法。   備註:   這個題目經常出現,包括Microsoft 等比較重視算法的公司都曾先後選用過個這道題

學習要趁早,專欄上新,早鳥訂閱送圖書

sant coo 變現 企業級 精品 阿根廷 玩轉 lov ech 51CTO博客專欄又有新內容了《負載均衡高手煉成記》從入門到實操,Linux老鳥帶你走上高並發架構之路。 為了貫徹學習要趁早的理念,我們特意為前100名訂閱專欄的小夥伴免費贈送紙質圖書一本,特別強調!!是!

喜迎學院周年慶,博客好禮送不停,51CTO博客專欄送書送T恤!!!

log 51cto 7月 負載 指定 定制 提升 圖書 訂閱 好禮一:訂閱新上專欄《負載均衡高手煉成記》就送自選圖書一本。 簡介:學習要趁早,你定專欄我送書,前100名(目前僅剩30名額)訂閱指定專欄就送圖書一本,為早鳥加餐,為夢想增值。 活動地址:學習要趁早,專欄上新,早

51CTO博客專欄匯總貼,聽說看了博客專欄的人工資都漲了~~

~~ 人工 lmap 入門到 案例 開發模式 路由 微服務 網站 新上專欄 專欄名稱:負載均衡高手煉成記簡介:老板要省錢,要求用負載均衡部署linux集群網站?負載均衡是衡量初中級以上運維技術水平的重要標尺?負載均衡是普通運維人員很難有機會接觸和系統學習的知識?本專欄依托

雷霄驊(leixiaohua1020)的專欄

過程 博客 .net title detail bsp -a 雷神 媒體播放 雷神的博客,很值得研究 https://blog.csdn.net/leixiaohua1020/article/list/28 RTMP流媒體播放過程 https://blog.csdn.n

博客專欄上新,早鳥訂閱送書,新上兩個專欄,總有一個你的菜。

nosql數據庫 集群架構 主從復制、 主從 mongodb 互聯 運維 一個 ron 專欄一:十年老兵教你練一套正宗的MySQL降龍十八掌 簡介:本專欄匯集了作者在MySQL運維及教學領域從業十年經驗,針對初學者量身定做,註重實例的操作與分析。由淺入深地剖析MySQL的體

不用每周等更新,一次訂閱看到爽,51CTO博客專欄更新完畢專欄合集

高級運維 com 容器雲 企業架構 公司 跟著 進行 高級工程師 狀態 51CTO博客訂閱專欄自上線以來就收到了廣大技術愛好者的支持,雖然以滿滿的幹貨俘獲了無數技術小哥哥的心,但是因為專欄內容每周更新一篇也讓無數技術小哥哥倍感煎熬。 BUT,現在已經有部分專欄內容已經更新完

周末炎熱不出門,難道宅家吃西瓜?精選助手為您帶來2個最新上線訂閱專欄,周末繼續漲知識

linux 高級 養成 web rip 設計 研究 高並發 javascrip 推薦專欄 一 訂閱專欄:JavaScript全棧工程師養成記 專欄作者:範濟穎(邊城),從事軟件開發 20 年,在軟件分析、設計、架構、開發及軟件開發技術研究和培訓等方面有著非常豐富的經驗,