6.824 Lab01 MapReduce

一些廢話:學(xué)6.824是因為實在是喜歡存儲括尸,不想再做監(jiān)控運維之類無聊的工作,想真正成長為一個專業(yè)的分布式存儲工程師病毡,也是看網(wǎng)上說6.824是分布式學(xué)習(xí)很好的入門課程濒翻,于是就利用空余時間開始學(xué)習(xí)這門課程。
這門課程的實驗都是推薦用golang實現(xiàn)的。其實用其他語言也是可以的有送,不過我覺得作為初學(xué)者淌喻,我還是用推薦語言去寫,后期遇到問題雀摘,也方便查詢參考資料裸删。而且語言不應(yīng)該是障礙,于是阵赠,在完成實驗中涯塔,我也用的是golang。一些go語言使用中清蚀,初學(xué)者會遇到的坑生蚁,也一一記錄下來你弦。

背景

首先了解一下MapReduce的背景,這個就直接搬課程內(nèi)容啦
Google需要在TB級別的數(shù)據(jù)上做大量計算,比如狞洋,為所有網(wǎng)頁創(chuàng)建索引,分析整個互聯(lián)網(wǎng)的鏈接路徑并得出最重要或最權(quán)威的網(wǎng)頁眼俊。Google需要一種框架慎颗,可以讓它的工程師能夠進行任意的數(shù)據(jù)分析,例如排序嘶卧,網(wǎng)絡(luò)索引器童本,鏈接分析器以及任何的運算。工程師只需要實現(xiàn)應(yīng)用程序的核心脸候,就能將應(yīng)用程序運行在數(shù)千臺計算機上穷娱,而不用考慮如何將運算工作分發(fā)到數(shù)千臺計算機,如何組織這些計算機运沦,如何移動數(shù)據(jù)泵额,如何處理故障等等這些細節(jié)。

原理

圖1 MapReduce 示意

重點理解:純函數(shù)式
Map函數(shù)使用一個key和一個value作為參數(shù)携添。入?yún)⒅屑廾ぃ琸ey是輸入文件的名字,通常會被忽略烈掠,因為我們不太關(guān)心文件名是什么羞秤,value是輸入文件的內(nèi)容content。
Reduce函數(shù)的入?yún)⑹悄硞€特定key的所有實例左敌,Reduce函數(shù)的入?yún)⑹悄硞€特定key的所有實例(Map輸出中的key-value對中瘾蛋,出現(xiàn)了一次特定的key就可以算作一個實例)。所以Reduce函數(shù)也是使用一個key和一個value作為參數(shù)矫限,其中value是一個數(shù)組哺哼,里面每一個元素是Map函數(shù)輸出的key的一個實例的value佩抹。


圖2 MapReduce原理

master給workers分配任務(wù)并記錄進度

  1. master將map任務(wù)給workers知道所有map任務(wù)完成, 將中間數(shù)據(jù)寫入磁盤,按哈希值將分割的輸出映射到每個Reduce任務(wù)的一個文件中取董。
  2. map任務(wù)結(jié)束后棍苹,master來處理reduce任務(wù),每個reduce任務(wù)獲得map任務(wù)的中間輸出茵汰,每個Reduce任務(wù)在GFS上寫一個單獨的輸出文件枢里。

實驗準(zhǔn)備

1.安裝go

【參考】http://www.reibang.com/p/49588471af18

$ wget https://golang.google.cn/dl/go1.15.6.linux-amd64.tar.gz
$ tar xz -C /usr/local -xzf go1.15.6.linux-amd64.tar.gz
創(chuàng)建工作目錄
$ mkdir -p ~/code/go
$ vim ~/.bashrc
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=/root/code/go
$ source ~/.bashrc
測試環(huán)境是否生效
$ go env

2.下載實驗參考代碼

6.824提供了完成實驗必要的一些通訊相關(guān)的代碼框架,可以幫助我們完成實驗

$ git clone git://g.csail.mit.edu/6.824-golabs-2020 6.824
$ cd 6.824
$ ls
Makefile src
$ cd ~/6.824
$ cd src/main
$ go build -buildmode=plugin ../mrapps/wc.go
$ rm mr-out*
$ go run mrsequential.go wc.so pg*.txt

mrsequential.go是非分布式實現(xiàn)的單詞計數(shù)任務(wù)蹂午,可以用來與分布式實現(xiàn)的mapreduce進行對比
課程說明提到開發(fā)一個分布式的mapreduce系統(tǒng)坡垫,由兩個程序組成:master和worker。一個master進程画侣,多個并行的worker進程冰悠。workers通過RPC和mater交互。每個worker進程問master要一個task配乱,從這個task中的input讀取一個或多個files溉卓,執(zhí)行這個task,將task的output寫入一個或多個文件搬泥,master需要注意一個worker是否在一段時間內(nèi)(10s)完成了task桑寨,如果沒完成,則把這個task給其他的worker忿檩。
課程設(shè)計已經(jīng)給了一段代碼幫助我們開始尉尾,The "main" routines for the master and worker are in main/mrmaster.go and main/mrworker.go,不要改這些files燥透。應(yīng)該把要實現(xiàn)的應(yīng)用放在mr/master.go, mr/worker.go, and mr/rpc.go沙咏。
編寫完mr里的代碼之后,如何run your code在word-count app上班套?

1.首先確認(rèn)wc.so已經(jīng)創(chuàng)建
$ go build -buildmode=plugin ../mrapps/wc.go
2.在main目錄肢藐,run master
$ rm mr-out*
$ go run mrmaster.go pg-*.txt
pg-*.txt參數(shù)是mrmaster.go的輸入文件,每個文件對應(yīng)一個“split”吱韭,是一個map task的輸入
3.在一個或多個窗口執(zhí)行workers
$ go run mrworker.go wc.so
4.通過a test script in main/test-mr.sh檢查wc和indexer
測試腳本檢查輸出是否正確吆豹,是否并行執(zhí)行,當(dāng)crash的worker恢復(fù)后tasks是否可以恢復(fù)
$ cd ~/6.824/src/main
$ sh test-mr.sh
*** Starting wc test.

開始實驗

雖然網(wǎng)上好多大神的經(jīng)驗貼都說lab01是灑灑水的理盆,很好實現(xiàn)痘煤,但學(xué)習(xí)這個事就是小馬過河,作為golang小白猿规,我覺得是不太容易的衷快,我做了整整1周。期間因為語言的不熟悉帶來一些磕磕絆絆坎拐,也記錄下來烦磁,幫助自己更快學(xué)會這門編程語言养匈,為后面的實驗打基礎(chǔ)哼勇。

Lab01的任務(wù)是實現(xiàn)一個簡單的mapreduce system都伪,我根據(jù)6.824給的代碼,自己根據(jù)學(xué)習(xí)進度做了一些簡單的調(diào)整积担。

1.mrsequential.go是一個例子陨晶,告訴我們,這個實驗不通過分布式帝璧,正常編碼是怎么樣的

1.1關(guān)于loadPlugin

實驗指導(dǎo)上在go run之前先執(zhí)行g(shù)o build -buildmode=plugin ../mrapps/wc.go來創(chuàng)建wc.so作為程序的plugin先誉,可是在操作過程中,發(fā)現(xiàn)windows對這個plugin的支持不是很好的樣子的烁,然后看代碼褐耳,這一步的必要性是啥?原來是涉及到一個函數(shù)loadPlugin

mapf, reducef := loadPlugin(os.Args[1])

上面這句其實就是要從wc.so中加載Map和Reduce函數(shù)渴庆,那如果不想用插件呢铃芦,也是容易的,直接函數(shù)賦值就好了襟雷。

//mapf, reducef := loadPlugin(os.Args[1])
var mapf func(string) []KeyValue
var reducef func(string, []string) string
mapf = Map
reducef = Reduce

接著看下mrsequential里有什么內(nèi)容

*KeyValue [stuct]
    //屬性
    Key刃滓、Value
    //要實現(xiàn)sort.Interface
    Len、Less耸弄、Swap
*Map [func]
*Reduce [func]
*main [func]

Map:輸入?yún)?shù)contents string咧虎,將contents分割成words,返回[]KeyValue{}數(shù)組计呈。
e.g
輸入:"This is a cat. That is a dog."
輸出:[{"This", "1"}, {"is", "1"},{"a", "1"},{"cat", "1"},{"That", "1"},{"is", "1"},{"a", "1"},{"dog", "1"}]

Reduce:輸入?yún)?shù)values []string砰诵,返回values數(shù)組的長度
*values就是"1"的數(shù)組

接下來看下main里面是怎么用Map和Reduce函數(shù)的,

Usage:mrsequential pg-*.txt

(1)intermediate是一個KeyValue的數(shù)組捌显,每個key出現(xiàn)一次胧砰,就增加一個{word,"1"}
遍歷每一個pg輸入文件苇瓣,將文件內(nèi)容讀入content,調(diào)用mapf尉间,加入intermediate數(shù)組
(2)將intermediate數(shù)組按照key排序,這樣击罪,相同的word會挨著
(3)遍歷intermediate數(shù)組
將擁有相同的key(word)的鍵值對合并哲嘲,一個key(word)的values傳遞給一個reducef
將key(word)和它的值輸出到文件mr-out-0

2.lab01需要的代碼
我們把這個任務(wù)分成三個部分main, mr, wc
main:

package main

mr:

package mr

wc:

package wc

每個package要導(dǎo)入其他package中的代碼一般用import來實現(xiàn),這邊有個golang的方法

$ cd /d/My/project/go/workspace/lab01/

$ go mod init lab01

這樣lab01目錄下就有一個go.mod

module lab01

go 1.15

這個時候代碼里再import就不用擔(dān)心GOROOT/GOPATH配置的問題

import lab01/mr
import lab01/wc

這邊也是為了在windows上調(diào)試方便媳禁,對代碼做出的小調(diào)整

3.golang rpc基本框架使用

知道了我們程序的最終目標(biāo)眠副,并且已經(jīng)把代碼框架提取出來,那分布式涉及到的rpc是怎么玩的呢竣稽?

main/mrmaster:
調(diào)用mr.MakeMaster啟動一個master的server囱怕,通過Done函數(shù)來監(jiān)聽霍弹,每次等1s

main/mrworker:
獲取wc定義的Map和Reduce函數(shù),調(diào)用mr.Worker來執(zhí)行mapf和reducef

那么接下來看下三個重要的步驟mr.MakeMaster娃弓,mr.Done典格,mr.Worker

都在mr里,好的台丛,那先看下mr的代碼結(jié)構(gòu)
mr/master

*Master [stuct]
    //屬性…自己寫
    //方法
    Example [func] //用來測試rpc
    server [func] //啟動一個server端耍缴,并通過go 開啟一個線程監(jiān)聽
    Done [func] //…自己寫

*MakeMaster [func] //定義一個Master,…自己寫,調(diào)用server()

mr/worker

*Worker [func]
    //…自己寫
    CallExample()//用來測試rpc

<pre style="background:white">其中args和reply都是用interface{}這個空接口類型定義的,這是為什么呢挽霉?原來go 語言規(guī)定防嗡,如果希望傳遞任意類型的變參,變參類型應(yīng)該制定為空接口類型侠坎,并且空接口可以指向任何數(shù)據(jù)對象蚁趁,所以可以使用interface{}定義任意類型變量。</pre>

rpc測試中master監(jiān)聽实胸,worker調(diào)用master中的Example方法他嫡,成功!

*CallExample [func]
    call("Master.Example", &args, &reply) //調(diào)用Master中的Example方法
*call [func]
特別說明下這個函數(shù)
func call(rpcname string, args interface{}, reply interface{}) bool {
}

rpcname是要調(diào)用的Master中定義的函數(shù)名
args是rpcname的輸入?yún)?shù)
reply是rpcname的返回值
其中args和reply都是用interface{}這個空接口類型定義的童芹,這是為什么呢涮瞻?原來go 語言規(guī)定,如果希望傳遞任意類型的變參假褪,變參類型應(yīng)該制定為空接口類型署咽,并且空接口可以指向任何數(shù)據(jù)對象,所以可以使用interface{}定義任意類型變量生音。

測試一下:

$ cd /d/My/project/go/workspace/lab01/main
$ go build mrmaster.go
$ go build mrworker.go
$./mrmaster.exe ../pg-*.txt
2021/01/06 16:10:24 rpc.Register: method "Done" has 1 input parameters; needs exactly three
$./mrworker.txt
reply.Y 100

rpc測試中master監(jiān)聽宁否,worker調(diào)用master中的Example方法,成功缀遍!

4.mapreduce實現(xiàn)
我畫了一個結(jié)構(gòu)圖便于自己以后想起來再看自己的代碼能懂的快一些(經(jīng)衬浇常看不懂自己寫的代碼星人的自我拯救)

6.824-lab01 代碼結(jié)構(gòu)說明

reference

第一個實驗,確實上手很不容易域醇,參考很多大神的資料台谊,在此感謝!
https://github.com/yzongyue/6.824-golabs-2020
https://zhuanlan.zhihu.com/p/187473895
https://blog.csdn.net/bysui/article/details/52128221
https://pdos.csail.mit.edu/6.824/schedule.html
【MIT公開課】6.824 分布式系統(tǒng) · 2020年春(完結(jié)·中英字幕·機翻)https://www.bilibili.com/video/BV1qk4y197bB?p=2
我的代碼都放在-》https://github.com/mengmayang/6.824-2020

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末譬挚,一起剝皮案震驚了整個濱河市锅铅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌减宣,老刑警劉巖盐须,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異漆腌,居然都是意外死亡贼邓,警方通過查閱死者的電腦和手機阶冈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塑径,“玉大人女坑,你說我怎么就攤上這事∠拢” “怎么了堂飞?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵灌旧,是天一觀的道長绑咱。 經(jīng)常有香客問我,道長枢泰,這世上最難降的妖魔是什么描融? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮衡蚂,結(jié)果婚禮上窿克,老公的妹妹穿的比我還像新娘。我一直安慰自己毛甲,他們只是感情好年叮,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著玻募,像睡著了一般只损。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上七咧,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天跃惫,我揣著相機與錄音,去河邊找鬼艾栋。 笑死爆存,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蝗砾。 我是一名探鬼主播先较,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼悼粮!你這毒婦竟也來了闲勺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤矮锈,失蹤者是張志新(化名)和其女友劉穎霉翔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苞笨,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡债朵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年子眶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片序芦。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡臭杰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谚中,到底是詐尸還是另有隱情渴杆,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布宪塔,位于F島的核電站磁奖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏某筐。R本人自食惡果不足惜比搭,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望南誊。 院中可真熱鬧身诺,春花似錦、人聲如沸抄囚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幔托。三九已至穴亏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柑司,已是汗流浹背迫肖。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留攒驰,地道東北人蟆湖。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像玻粪,于是被迫代替她去往敵國和親隅津。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容