MIT6.824-Lab1實現筆記
原文說明
In this lab you’ll build a MapReduce library as an introduction to programming in Go and to building fault tolerant distributed systems. In the first part you will write a simple MapReduce program. In the second part you will write a Master that hands out tasks to MapReduce workers, and handles failures of workers. The interface to the library and the approach to fault tolerance is similar to the one described in the original MapReduce paper.
這個Lab的目的是,首先用Golang構建一個MapReduce庫練練手,然後實現一個具有容錯能力的分散式系統。第一部分實現一個簡單的MapReduce程式。第二個部分實現一個Master用來排程任務並且處理worker失敗的情況。該MapReduce庫的介面以及容錯處理策略跟ofollow,noindex" target="_blank">Google的MapReduce論文(下文用論文代替) 中描述的一致。
題目
Part I: Map/Reduce input and output
這個問題就是完善基本的MapReduce庫的核心邏輯,核心就是實現mapreduce/common_map.go:doMap()以及mapreduce/common_reduce.go:doReduce()函式。
Part II: Single-worker word count
基於Part I實現一個具有單一worker的單詞計數程式。主要實現main/wc.go:mapF()和reduceF()函式。
Part III: Distributing MapReduce tasks
給MapReduce增加分散式能力,將任務排程到不同的worker上。主要邏輯在mapreduce/schedule.go:schedule()函式中。
Part IV: Handling worker failures
容錯能力,處理當worker出現錯誤時的情況。所以,處理位置也在Part III的schedule()中。
Part V: Inverted index generation (optional, does not count in grade)
又一個MapReduce的應用,反轉索引。
實現
MapReduce庫的基本框架
在進入每部分實現之前,有必要分析下整個框架的實現。
Part I
這一部分的邏輯是理解整個MapReduce的基礎。所以有必要好好實現下。
Map 任務
-
引數說明
- jobName string: MapReduce任務的名字,主要是用於產生中間檔案的命名。
- mapTask int: map任務的序號,因為map任務會有很多個,每個都有一個編號,所以這裡用於區分不同的任務。
- inFile string: map任務待處理的檔名。
- nReduce int: 有多少個reduce任務,主要用於分割reduce任務用到的中間檔案,參考論文中的R變數。
- mapF: 每種任務自定義的map函式。
- 輸出結果:Num(map) * Num(reduce) 個臨時檔案
-
邏輯
總起來說就是,讀取待處理的檔案inFile,將檔案內容傳遞給map函式,最後將返回的kv集合寫入臨時檔案。
map任務無非就是將內容轉換為某種kv集合的行為。每種map任務都有不同的業務邏輯。通常我們說的實現一個MapReduce任務應該就是實現這裡的mapF還有下文的reduceF函式。
論文中明確了map任務的結果為啥要寫入臨時檔案。比較關鍵的是臨時檔案的命名以及寫入邏輯:
- 首先,針對kv集合中的key做一次hash得到h
- 然後,對reduce的任務數做一次取模得到r
- 最後,按一定的規則生成中間檔名字——不同的庫可以有不同的邏輯,關鍵是一致性,reduce任務應該能理解。每個Map任務都會產生nReduce個臨時檔案,所以總共會產生Num(map)*Num(reduce)個臨時檔案
- 寫入的時候,一般都會進行編碼,編碼規則也可以自定義,需要reduce任務能理解就好
-
實現
Map任務實現起來比較簡單,所以我基本上沒有遇到什麼坑。
參考:
Reduce 任務
-
引數說明
- jobName string: MapReduce任務的名字,主要是用於產生中間檔案的命名。
- reduceTask int: Reduce任務會有多個,這裡是某個Reduce任務的序號。
- outFile string: MapReduce任務的輸出結果檔案。
- nMap int: 有多少個Map任務,對應論文中的M變數。
- reduceF: 每種任務自定義的reduce函式。
- 輸出結果:nReduce個臨時結果檔案。
-
邏輯
Reduce任務的輸入是上文Map任務產生的臨時檔案,每個Map任務都會產生供這個Reduce任務處理的臨時檔案,所以要針對每個Map任務獲取臨時檔案——這一點是我在梳理這塊邏輯時才真正弄明白的,所以看懂並理解與真正實現還差著好遠呢。
當把所有的中間檔案都讀取並解碼(上文Map寫入時做的編碼)之後,提取到kv集合,將其傳遞給reduce處理後,寫入磁碟產生輸出檔案即完成了Reduce任務。
-
實現
實現Reduce任務的時候有點費勁,歸根到底是當時並沒有真正理解MapReduce執行的具體原理。這裡面的關鍵點是,每個Reduce任務的輸入是所有Map任務都會產生的。所以要蒐集這些個臨時檔案並處理。
Merge 任務
這個Lab並沒有讓實現這塊邏輯。其主要任務就是將nReduce個臨時結果檔案合併後產生一個完整的結果檔案。
Task II
在理解了基本的MapReduce實現原理之後,做一個小demo是很有必要的,單詞計數就是這個目的。
實現每個Map任務,最重要的就是要回答一個問題:任務處理後生成的kv對的格式是怎樣的。
Map 任務
-
引數說明
- filename string: 每個Map任務所需要處理的檔名
- contents string: 每個Map任務所需要處理的檔案內容
-
實現
該demo的kv對的格式是:key為每個單詞,value是一個用於計數的標籤,我這裡用數字1來表示。
我直接用1來表示一個單詞,所以沒有去重。我覺得也許在這裡計算每個單詞的個數更好,由於只是用於demo,後續有需要再優化吧。
Reduce 任務
後記
-
pingworld.cn/%E7%94%9F%E6%B4%BB/2018/11/13/%E6%99%A8%E8%B7%91/" rel="nofollow,noindex" target="_blank">
Previous
晨跑