MIT 6.824分布式系統(tǒng)課程眶蕉,是一門著名的講解分布式系統(tǒng)設(shè)計(jì)原理的課程。通過課程講解和實(shí)驗(yàn)結(jié)合來學(xué)習(xí)分布式系統(tǒng)設(shè)計(jì)原理冠胯,實(shí)驗(yàn)和課程安排見課程表阀蒂。
前言
我為什么要學(xué)習(xí)這個(gè)課程?之所以會(huì)接觸到這門課程汤徽,是之前在表示對(duì)分布式系統(tǒng)感興趣時(shí)一位基友介紹的娩缰,由于種種原因并沒有開始學(xué)。直到最近谒府,開始研究分布式緩存系統(tǒng)的設(shè)計(jì)才重新開始拼坎。有讀過筆者之前的文章可能知道,筆者對(duì)redis的研究內(nèi)容比較感興趣完疫,后面對(duì)redis如何做分布式緩存比較感興趣泰鸡,于是開始查資料,后來發(fā)現(xiàn)etcd在這方面也很強(qiáng)壳鹤,在學(xué)習(xí)etcd過程中又了解到了到了raft協(xié)議盛龄,接著就查到了這門課程中有介紹Raft協(xié)議的論文以及相關(guān)的實(shí)驗(yàn),剛好得知2020年春季的課程有官方版的視頻且被熱心網(wǎng)友分享到B站了芳誓,再加上完成實(shí)驗(yàn)需要用go語言來實(shí)現(xiàn)余舶,基于學(xué)習(xí)分布式系統(tǒng)設(shè)計(jì)原理和實(shí)踐go語言的目的,于是就開始學(xué)習(xí)這門課程锹淌。
實(shí)際上匿值,etcd和redis是完全不一樣概念的東西,etcd主要用于分布式鎖以及集群核心配置赂摆,核心特性是高可用挟憔;而Redis是內(nèi)存型數(shù)據(jù)庫钟些,目的是做分布式緩存,保存數(shù)據(jù)绊谭。
準(zhǔn)備資料
學(xué)習(xí)這門課程政恍,是先閱讀了課程主頁的介紹,接著根據(jù)課程表去學(xué)習(xí)达传,課程表里說明了先閱讀論文后再去上課(或者看視頻)篙耗,要先看論文后再去看視頻,否則看視頻時(shí)教授在講什么都不知道趟大。
上課步驟就是:讀論文->看視頻->做實(shí)驗(yàn)鹤树。
MapReduce簡介
通過學(xué)習(xí)論文、課程視頻以及完成了實(shí)驗(yàn)逊朽,對(duì)MapReduce有了個(gè)初步的認(rèn)識(shí)罕伯,在這里總結(jié)一下我的理解。
MapReduce叽讳,本質(zhì)就是一種編程模型追他,也是一個(gè)處理大規(guī)模數(shù)據(jù)集的相關(guān)實(shí)現(xiàn)。之所以會(huì)有這個(gè)模型岛蚤,目的是為了隱藏“并行計(jì)算邑狸、容錯(cuò)處理、數(shù)據(jù)分發(fā)涤妒、負(fù)載均衡”单雾,從而實(shí)現(xiàn)大數(shù)據(jù)計(jì)算的一種抽象。
MapReduce的編程模型:
map:接收一組輸入的key/value鍵值對(duì)她紫,處理后生成一組被稱為中間值的key/value鍵值對(duì)集合硅堆。
reduce:輸入是map生成的key/value鍵值對(duì)集合,合并中間值集合中相同key的值贿讹。
整個(gè)處理過程的抽象過程如下:
在分布式系統(tǒng)中渐逃,除了程序以外還有很多需要考慮的問題,比如并發(fā)民褂、容錯(cuò)處理等等茄菊,對(duì)于分布式的MapReduce,執(zhí)行概覽看下面這幅經(jīng)典的流程圖:
從圖里可以看到赊堪,Map和Reduce程序分布在多臺(tái)機(jī)器面殖,取出分片數(shù)據(jù)來處理,數(shù)據(jù)可以被多臺(tái)機(jī)器并行地處理哭廉,而如何分發(fā)數(shù)據(jù)及程序的管理由Worker和Master組成脊僚。執(zhí)行的流程大致如下:
系統(tǒng)會(huì)啟動(dòng)一個(gè)或多個(gè)Master,需要執(zhí)行任務(wù)的機(jī)器啟動(dòng)Worker來處理任務(wù)群叶。Master主要職責(zé)是分配任務(wù)給Worker吃挑,Master可以隨機(jī)選擇空閑的Worker來分配任務(wù),或者Worker主動(dòng)向Master請(qǐng)求任務(wù)街立;
獲得map任務(wù)的Worker舶衬,讀取數(shù)據(jù)分片,生成一組key/value鍵值對(duì)的中間值集合赎离,并將數(shù)據(jù)寫到本地文件逛犹,這里每個(gè)map任務(wù)數(shù)據(jù)分為R份(Master創(chuàng)建reduce任務(wù)的數(shù)量),通過用戶定義的分區(qū)函數(shù)(如hash(key) mod R)決定將key存在哪個(gè)文件梁剔;
獲得reduce任務(wù)的Worker虽画,通過遠(yuǎn)程調(diào)用請(qǐng)求數(shù)據(jù),數(shù)據(jù)加載完畢后荣病,對(duì)數(shù)據(jù)進(jìn)行排序码撰,之后遍歷數(shù)據(jù),將相同key的數(shù)據(jù)進(jìn)行合并个盆,最終輸出結(jié)果脖岛;
當(dāng)所有的map和reduce任務(wù)完成了,整個(gè)MapReduce程序就處理完畢了颊亮,Worker得到處理后的數(shù)據(jù)柴梆,通常會(huì)保存在不同的小文件中,合并這些文件之后就是最重要的結(jié)果终惑。
以上就是我對(duì)MapReduce論文的理解總結(jié)绍在,還有其他的本地化、任務(wù)粒度雹有、合并和排序程序偿渡、性能等等話題,因?yàn)樵趯?shí)驗(yàn)里還沒很深的印象件舵,所以這里暫不進(jìn)行說明卸察。
另外要重點(diǎn)關(guān)注的是容錯(cuò)處理,如果Master中斷铅祸、Worker程序崩潰坑质,這些情況要怎么處理?論文里提到的解決方案是將處理結(jié)果保存在臨時(shí)文件中临梗,等到任務(wù)真正處理完才寫到待輸出文件里涡扼。
實(shí)驗(yàn)完成之路
無法入手
讀完MapReduce論文后,去看課程的前兩節(jié)視頻盟庞,聽懂了大部分吃沪,然后興致勃勃開始做實(shí)驗(yàn)。代碼拉下來之后什猖,發(fā)現(xiàn)根本沒法下手票彪,對(duì)著實(shí)驗(yàn)題和代碼苦惱了一個(gè)晚上红淡,只知道實(shí)驗(yàn)1就是要實(shí)現(xiàn)一個(gè)分布式的MapReduce,但是看代碼已經(jīng)有了map和reduce函數(shù)降铸,根本不知道要做什么在旱,感覺還沒開始就要結(jié)束了。
反復(fù)學(xué)習(xí)資料
第一次開始做實(shí)驗(yàn)失敗之后推掸,花了幾個(gè)晚上將論文反復(fù)看了兩遍桶蝎,再回去看視頻,在第二次的學(xué)習(xí)里谅畅,印象更加深刻了登渣,再反復(fù)看題目的說明,說明里提到每次修改完程序后毡泻,都要執(zhí)行test-mr.sh胜茧,里面包含了很多測試用例,只要通過了所有測試用例牙捉,那么實(shí)驗(yàn)就算完成了竹揍。于是去看測試用例文件,再結(jié)合題目描述邪铲,終于知道要做什么了芬位。
測試先行,閱讀test-mr.sh可以發(fā)現(xiàn)带到,里面主要包含了5個(gè)測試用例:單詞計(jì)數(shù)mapreduce昧碉、索引mapreduce、并行map揽惹、并行reduce被饿、程序崩潰。比如單詞計(jì)數(shù)搪搏,檢查的步驟是先運(yùn)行mrsequential.go輸出一個(gè)文件mr-correct-wc.txt狭握,接著啟動(dòng)mrmaster和mrworker,得到結(jié)果后合并為mr-wc-all文件疯溺,比較兩個(gè)文件內(nèi)容一樣就說明通過該用例了论颅。那么要完成實(shí)驗(yàn)要,可以先看看mrsequential.go里面做了什么囱嫩,寫一個(gè)分布式程序去實(shí)現(xiàn)mrsequential.go的功能恃疯。
只要完成了以上的5個(gè)測試用例,實(shí)驗(yàn)就算完成了墨闲,而實(shí)際上map和reduce程序已經(jīng)實(shí)現(xiàn)好了今妄,那么需要做的是實(shí)現(xiàn)論文里提到的master和worker:
1、如何分配任務(wù)?map和reduce任務(wù)如何分配盾鳞?(用例1犬性、用例2)
2、如何實(shí)現(xiàn)并行處理腾仅?(用例3仔夺、用例4)
3、怎么判斷Worker崩了攒砖?Worker失敗后,如何恢復(fù)日裙,如何處理正在處理中的任務(wù)吹艇?(用例5)
4、任務(wù)處理完成后昂拂,結(jié)果如何處理?
5、Worker和Master之間的通信通過rpc通信忘瓦,如何維持兩者間的狀態(tài)吱晒?
理清了需求是要做什么以后,接下來就是設(shè)計(jì)和編碼了联四。
系統(tǒng)設(shè)計(jì)
只要是程序撑碴,設(shè)計(jì)起來都不外乎數(shù)據(jù)結(jié)構(gòu)和算法,對(duì)于這個(gè)實(shí)驗(yàn)而言朝墩,也是如此醉拓。
數(shù)據(jù)結(jié)構(gòu)
定義Master和Task的數(shù)據(jù)結(jié)構(gòu)如下:
type Master struct {
nReduce int
nMap int
mapTasks []Task
reduceTasks []Task
state int // MASTER_INIT;MAP_FINISHED;REDUCE_FINISHED
mapTaskFinishNum int
reduceTaskFinishNum int
}
type Task struct {
State int // TASK_INIT;TASK_PROCESSING;TASK_DONE
InputFileName string
Id int
OutputFileName string
TaskType int // MAP_TASK;REDUCE_TASK
NReduce int
NMap int
StartTime int64
}
實(shí)現(xiàn)流程圖
根據(jù)對(duì)論文以及實(shí)驗(yàn)題目的理解后,設(shè)計(jì)Master和Task兩個(gè)結(jié)構(gòu)體收苏,要實(shí)現(xiàn)的功能如下圖:
1亿卤、啟動(dòng)Master后,Master狀態(tài)為INIT鹿霸,并根據(jù)啟動(dòng)參數(shù)初始化map任務(wù)
2排吴、啟動(dòng)Worker,請(qǐng)求Master分配一個(gè)任務(wù)懦鼠,然后處理任務(wù)(map/reduce)
3钻哩、處理完成后通知Master更新任務(wù)狀態(tài)為完成;每次有任務(wù)完成時(shí)葛闷,檢查Map/Reduce任務(wù)是否全部完成憋槐,根據(jù)完成進(jìn)度更新Master狀態(tài)
4、所有任務(wù)完成后淑趾,Master狀態(tài)為REDUCE_FINISHED
崩潰處理
關(guān)于處理worker崩潰阳仔,實(shí)驗(yàn)提示里提到,Master不能明顯區(qū)分出Worker是處理超時(shí)還是崩潰了,所以需要設(shè)計(jì)一個(gè)超時(shí)時(shí)間(如10秒)近范,如果任務(wù)超時(shí)了嘶摊,就認(rèn)為任務(wù)未完成,下一次再重新分配评矩。實(shí)現(xiàn)是在Master分配一個(gè)任務(wù)時(shí)叶堆,初始化一個(gè)開始時(shí)間,Master分配任務(wù)時(shí)斥杜,檢查進(jìn)行中任務(wù)虱颗,如果任務(wù)還未完成且超時(shí)了,就重新分配該任務(wù)給Worker蔗喂。
ALL PASS
所有測試用例都通過的那一刻忘渔,內(nèi)心有一份小小的激動(dòng),仿佛上大學(xué)時(shí)通過了一道實(shí)驗(yàn)題那種感覺缰儿。
Q&A
分享幾點(diǎn)學(xué)習(xí)中遇到的問題:
1畦粮、學(xué)習(xí)這個(gè)有什么用?
這個(gè)問題比較尖銳了乖阵,我的理解就是宣赔,如果對(duì)分布式系統(tǒng)感興趣,想通過實(shí)踐來強(qiáng)化對(duì)分布式系統(tǒng)的理解瞪浸,那么學(xué)習(xí)這個(gè)課程會(huì)有幫助儒将。如果不感興趣的話,那么這篇文章對(duì)你沒有什么用对蒲。
2椅棺、如何開始學(xué)習(xí)?
看課程主頁齐蔽,根據(jù)課程表安排两疚,先看論文,在看視頻含滴,理解個(gè)大概后開始做實(shí)驗(yàn)诱渤,然后再看論文和視頻加深理解。
3谈况、看完了視頻勺美,實(shí)驗(yàn)程序怎么跑起來?怎么開始寫下第一行代碼碑韵?
準(zhǔn)備一點(diǎn)Go語言的基礎(chǔ)赡茸,開始做時(shí)多看題目的提示,比如提示的第一點(diǎn)說到祝闻,讓代碼跑起來的第一步就是修改mr/worker.go的Worker函數(shù)占卧,發(fā)一個(gè)RPC請(qǐng)求到Master,請(qǐng)求一個(gè)任務(wù)數(shù)據(jù)。
4华蜒、論文辙纬、課程和題目都是英文版的,看不懂怎么辦叭喜?
硬著頭皮看贺拣,不懂的就去翻譯,當(dāng)然可以看中文版捂蕴,網(wǎng)上有很多資源譬涡。課程視頻有熱心網(wǎng)友做了個(gè)中文字幕,可以看中文字幕啥辨。
另外昂儒,多說一句,還是推薦盡量看英文版的委可,并沒有崇洋媚外的意思,只不過對(duì)于程序開發(fā)而言腊嗡,英文能力還是一個(gè)必備技能着倾,因?yàn)槠綍r(shí)查問題的時(shí)候都是英文資料比較多,而且讀一手的資料是最好的燕少,這篇文章也只不過是我消化完的知識(shí)分享卡者,有可能論文和課程里還有很多我看不到但是你看得到的東西。
5客们、有代碼鏈接嗎崇决?
程序員名言:talk is cheep, show me the code.但是由于課程強(qiáng)調(diào)了盡量不要看別人的實(shí)現(xiàn),也有人放到Github被MIT要求刪除過底挫,所以筆者就不共享全部代碼了恒傻,如果有需要可私下交流。
總結(jié)
通過學(xué)習(xí)前兩課建邓,完成MapReduce這個(gè)實(shí)驗(yàn)盈厘,對(duì)分布式系統(tǒng)有了一個(gè)最表面的認(rèn)識(shí),還談不上掌握官边,這只是一個(gè)最簡單的實(shí)驗(yàn)沸手,更重點(diǎn)的課程和實(shí)驗(yàn)還在后面,路漫漫其修遠(yuǎn)兮注簿。
如果你也在學(xué)習(xí)契吉,希望這篇文章對(duì)你有幫助。歡迎有興趣的同學(xué)來一起學(xué)習(xí)討論诡渴。
原創(chuàng)文章捐晶,文筆有限,才疏學(xué)淺,文中若有不正之處租悄,萬望告知谨究。
如果本文對(duì)你有幫助,請(qǐng)點(diǎn)個(gè)贊吧泣棋,謝謝_