簡單記錄一下,方便自己查看
開始實驗
先用git下載實驗的代碼框架
$ git clone git://g.csail.mit.edu/6.824-golabs-2020 6.824
它提供的src/main/mrsequential.go
是一個順序mapreduce實現,在單進程中執行map和reduce操作1次。
mrapps/wc.go
和mrapps/indexer.go
是兩個MapReduce應用。
舉例運行wc.go
$ cd ~/6.824
$ cd src/main
$ go build -buildmode=plugin ../mrapps/wc.go
$ rm mr-out*
$ go run mrsequential.go wc.so pg*.txt
$ more mr-out-0
A 509
ABOUT 2
ACT 8
...
mrequential.go
將其輸出保留在文件mr-out-0
中。 它的輸入來自名為pg-xxx.txt的文本文件。
可以隨意從mrequential.go借用代碼。
任務
實現一個分布式MapReduce,它由兩個程序(master程序和worker程序)組成。
它將只有一個master進程以及一個或多個並行執行的worker進程。
在真實系統中,工作人員將在多台不同的機器上運行,但在本實驗中,將在一台機器上運行它們。
worker通過RPC遠程調用與Master對話。
每個Worker進程將向Master進程請求一個任務,從一個或多個文件讀取任務的輸入,執行任務,並將任務的輸出寫入一個或多個文件。
如果一個Worker沒有在合理的時間內完成任務(本實驗規定10秒),Master應該將該任務交給另一個Worker。
Master和Worker的main例程在main/mrmaster.go
和main/mrworker.go
中,不要改動這些程序。
需要在mr/master.go
,mr/worker.go
和mr.rpc.go
中實現自己的代碼。
舉例在單詞統計wc.go
這個MapReduce應用程序上運行代碼:
- 當前在main目錄下,需要確保word-count插件是新構建的:
$ go build -buildmode=plugin ../mrapps/wc.go
-刪除原來的輸入(可能不存在),執行master代碼
$ rm mr-out*
$ go run mrmaster.go pg-*.txt
- 在多個窗口中運行worker代碼
$ go run mrworker.go wc.so
- 當worker和master都完成,在
mr-out-xxx
查看輸出。輸出文件的排序並集應與順序輸出匹配,用cat命令查看
$ cat mr-out-* | sort | more
A 509
ABOUT 2
ACT 8
...
在main/test-mr.sh
中有一個測試腳本,測試在給定pg-xxx.txt文件作為輸入的情況下,檢查wc和indexer MapReduce應用程序是否產生正確的輸出。
這些測試還檢查自己的實現是否並行運行Map和Reduce任務,以及Worker能否在運行任務崩潰時恢復。
如果現在直接運行測試腳本,他將會一直運行,因為master死循環。
$ cd ~/6.824/src/main
$ sh test-mr.sh
*** Starting wc test.
可以在mr/master.go
的Done函數中更改ret:=false
為ret:=true
,master就會立即結束。
$ sh ./test-mr.sh
*** Starting wc test.
sort: No such file or directory
cmp: EOF on mr-wc-all
--- wc output is not the same as mr-correct-wc.txt
--- wc test: FAIL
$
測試腳本期望在名為MR-OUT-X的文件中看到輸出,每個Reduce任務對應一個文件。
mr/master.go和mr/worker.go的空實現不會生成這些文件(或執行許多其他操作),因此測試失敗。
完成后,測試腳本輸出應如下所示:
$ sh ./test-mr.sh
*** Starting wc test.
--- wc test: PASS
*** Starting indexer test.
--- indexer test: PASS
*** Starting map parallelism test.
--- map parallelism test: PASS
*** Starting reduce parallelism test.
--- reduce parallelism test: PASS
*** Starting crash test.
--- crash test: PASS
*** PASSED ALL TESTS
$
Go RPC軟件包可能會有一些類似如下的提示,忽略這些信息
rpc.Register: method "Done" has 1 input parameters; needs exactly three
一些規則:
-
map階段應將中間鍵划分為用於
nReduce
reduce任務的存儲桶,其中nReduce
是main/mrmaster.go
傳遞給MakeMaster()
的參數。 -
Worker實現應將第X個reduce任務的輸出放在文件mr-out-X中。
-
一個
mr-out-X
文件的每個Reduce函數輸出應包含一行。 以Go中“%v%v”格式輸出鍵和值。 在main/mrsequential.go
中查看注釋為“這是正確的格式”的行。 如果偏離此格式太多,則測試腳本將失敗。 -
可以修改mr/worker.go、mr/master.go和mr/rpc.go。可以臨時修改其他文件進行測試,但請確保使用原始版本進行最終測試。
-
worker應該將中間映射輸出放在當前目錄中的文件中,這樣稍后worker可以將它們讀取他們作為Reduce任務的輸入。
-
main/mrmaster.go
期望mr/master.go
實現Done()方法,該方法在MapReduce作業完全完成時返回true,結束mrmaster.go程序。 -
作業完全完成后,Worker進程應退出。一種簡單的實現方法是使用call()的返回值:如果Worker進程無法聯系Master進程,則可以假定Master進程已經退出,因為任務已經完成,因此worker進程也可以終止。根據該設計,Master可以交給Worker的“請退出”的偽任務會很有幫助。
提示
-
開始任務的一種方法是修改
mr/worker.go
的worker()
,以便向Master發送請求任務的RPC。然后修改master以響應一個尚未啟動的映射任務的文件名。然后修改Worker以讀取該文件並調用應用程序Map函數,如mrequential.go
中所示。 -
使用Go插件包在運行時從名稱以.so結尾的文件中加載應用程序Map和Reduce函數。
-
如果更改了
mr/
目錄中的任何內容,則可能需要使用類似於go build-buildmode=plugin../mrapps/wc.go
的命令重新構建MapReduce插件。 -
本實驗的worker依賴於共享文件系統。 當所有worker在同一台機器上運行時,這很簡單,但是如果worker運行在不同的機器上,則需要GFS這樣的全局文件系統。
-
中間文件的合理命名約定是mr-X-Y,其中X是Map任務編號,Y是Reduce任務編號。
-
worker的map任務代碼將需要一種方法來存儲文件中的中間鍵/值對,這種方法可以在reduce任務期間正確讀取。一種可能是使用Go的encoding/json包。要將鍵/值對寫入JSON文件,請執行以下操作:
enc := json.NewEncoder(file)
for _, kv := ... {
err := enc.Encode(&kv)
要讀回這樣的文件,請執行以下操作:
dec := json.NewDecoder(file)
for {
var kv KeyValue
if err := dec.Decode(&kv); err != nil {
break
}
kva = append(kva, kv)
}
-
Worker的map部分可以使用
ihash(Key)
函數(在worker.go中)為給定的鍵選擇Reduce任務。 -
可以從
mrequential.go
竊取一些代碼,用於讀取Map輸入文件,對Map和Reduce之間的中間鍵/值對進行排序,以及在文件中存儲Reduce輸出。 -
作為RPC服務器的master將是並發的;不要忘記鎖定共享數據。
-
使用Go的race檢測器,與
go build -race
和go run -race
一起使用。test-mr.sh
的注釋展示了如何為測試啟用race檢測器。 -
worker有時需要等待,例如 在最后一個map任務完成之前,reduce無法開始。一種可能是worker定期向master請求工作,在每次請求之間用
time.Sleep()
休眠。另一種方法是,Master中的相關RPC處理程序有一個等待的循環,可以是time.Sleep()
,也可以是sync.Cond
。GO在其自己的線程中為每個RPC運行處理程序,因此一個處理程序正在等待的事實不會阻止主處理程序處理其他RPC。 -
Master無法可靠地區分崩潰的worker,活着的但由於某種原因停工的worker和執行但速度太慢而無法使用的worker。可以讓master等待一段時間,然后放棄並將任務重新分配給不同的worker。對於本實驗,讓master等待10秒,之后,master應該假定工人已經死亡(當然,它可能沒有死)。
-
要測試崩潰恢復,可以使用mrapps / crash.go應用程序插件。 它在Map和Reduce函數中隨機退出。
-
為了確保在崩潰時沒有人觀察到部分寫入的文件,MapReduce的論文提到了使用臨時文件並在完全寫入后自動重命名的技巧。可以使用
ioutil.TempFile
創建臨時文件,使用os.Rename
自動重命名它。 -
test-mr.sh
運行子目錄mr-tmp`中的所有進程,因此,如果出現問題,並且希望查看中間文件或輸出文件,請在此處查找。