注:這篇博客講的是自己對(duì)Spark的初步認(rèn)識(shí)和學(xué)習(xí),可能會(huì)有錯(cuò)誤橄教。參考資料是廈門大學(xué)的Spark學(xué)習(xí)基礎(chǔ)橄维,對(duì)應(yīng)網(wǎng)址上有關(guān)于Spark運(yùn)行機(jī)制的6個(gè)視頻的講解(3.3節(jié))枣接,更加通俗易懂证舟。
??首先需要了解Spark中的一些核心概念:
- RDD硕旗,最核心的數(shù)據(jù)抽象,全稱是彈性分布式數(shù)據(jù)女责,是高度受限(只讀)的共享內(nèi)存模型
- DAG漆枚,反映了RDD之間的依賴關(guān)系
- Executor,在工作節(jié)點(diǎn)(就是單個(gè)機(jī)器)上的一個(gè)進(jìn)程抵知,會(huì)派生很多線程來(lái)執(zhí)行任務(wù)
- application墙基,就是Spark程序
- 任務(wù),在Executor上運(yùn)行的工作單元
- 階段辛藻,作業(yè)job的基本調(diào)度單元
??然后了解下Spark的架構(gòu):
Spark大概可以分為3個(gè)部分碘橘,第一個(gè)是任務(wù)控制節(jié)點(diǎn)互订,其實(shí)就是程序中的SparkContext(返回一個(gè)RDD)吱肌;第二個(gè)是集群資源管理器,一般是用yarn來(lái)進(jìn)行集群的管理仰禽;最后一個(gè)就是集群上的工作節(jié)點(diǎn)work node氮墨,每個(gè)work node上都包含了一個(gè)Executor用來(lái)執(zhí)行部分任務(wù)。最后多個(gè)work node的結(jié)果匯總就可以寫到HDFS或者HBase上吐葵。
相應(yīng)的规揪,Spark運(yùn)行流程大概就是,sparkContext會(huì)像資源管理器申請(qǐng)資源温峭,而資源管理器(一般是yarn)會(huì)對(duì)集群進(jìn)行調(diào)度猛铅,并將部分work node分配給申請(qǐng)的SparkContext(資源分配的原則是計(jì)算向數(shù)據(jù)靠攏)。然后我們的SparkContext會(huì)被分成多個(gè)作業(yè)job(分而治之嘛)凤藏,同時(shí)奸忽,SparkContext也會(huì)輸出一個(gè)根據(jù)RDD依賴關(guān)系生成的DAG,這個(gè)DAG通過(guò)DAG Scheduler將job分為多個(gè)階段揖庄,每個(gè)階段會(huì)在相應(yīng)work node上執(zhí)行任務(wù)栗菜。最后將所有work node上的工作進(jìn)行匯總得到最終結(jié)果。
??接著了解下RDD的執(zhí)行過(guò)程:
其實(shí)Spark運(yùn)行流程就是RDD執(zhí)行過(guò)程蹄梢,HDFS上的數(shù)據(jù)讀到內(nèi)存中生成RDD疙筹,RDD經(jīng)過(guò)多次轉(zhuǎn)換(RDD->RDD),然后經(jīng)過(guò)動(dòng)作(RDD->value)并輸出結(jié)果。這里我們需要記住的是而咆,整個(gè)運(yùn)行過(guò)程遵循著惰性調(diào)用機(jī)制霍比,直白點(diǎn)說(shuō)就是轉(zhuǎn)換過(guò)程延遲執(zhí)行,機(jī)器只是記住了要如何對(duì)RDD進(jìn)行轉(zhuǎn)換暴备,但不會(huì)真正去執(zhí)行這個(gè)轉(zhuǎn)換桂塞,只有當(dāng)遇到動(dòng)作時(shí)RDD才會(huì)開始執(zhí)行所有流程,包括前面的轉(zhuǎn)換和當(dāng)前的動(dòng)作馍驯,最后得到結(jié)果阁危。也就是說(shuō),轉(zhuǎn)換只記錄數(shù)據(jù)變換軌跡汰瘫,機(jī)器并不會(huì)進(jìn)行真正的計(jì)算狂打,而動(dòng)作則會(huì)觸發(fā)從頭到尾的計(jì)算。
Spark對(duì)原Hadoop的一大優(yōu)勢(shì)就是RDD的優(yōu)化縮短了程序運(yùn)行時(shí)間混弥,這個(gè)優(yōu)化體現(xiàn)在流水線處理和中間結(jié)果不寫入磁盤(利用RDD的.cache()將數(shù)據(jù)存在內(nèi)存中)趴乡。而Spark的另外一個(gè)優(yōu)勢(shì)就是高效容錯(cuò)性,傳統(tǒng)保證容錯(cuò)率的方式是數(shù)據(jù)備份或者日志蝗拿,但是在大數(shù)據(jù)場(chǎng)景下開銷太大不合適晾捏,而Spark根據(jù)DAG得到的計(jì)算過(guò)程中數(shù)據(jù)的血緣關(guān)系可以很方便的找回丟失數(shù)據(jù)。
流水線處理就是指讓work node自己獨(dú)立完成盡可能多的工作哀托,而不必要等其他work node工作完一起join一下然后接著后面的處理惦辛,這樣就可以避免工作快的work node去等待工作慢的work node,節(jié)約了很多的等待時(shí)間仓手。為了盡可能做到這一點(diǎn)胖齐,就需要將每個(gè)job分為多個(gè)階段。如果將RDD任務(wù)中的轉(zhuǎn)換和動(dòng)作看做一個(gè)個(gè)節(jié)點(diǎn)嗽冒,那么如果將這些節(jié)點(diǎn)劃分到不同階段里呢呀伙?那就得看節(jié)點(diǎn)之間是否有數(shù)據(jù)的shuffle。如果兩個(gè)節(jié)點(diǎn)之間沒(méi)有數(shù)據(jù)shuffle添坊,那么這兩個(gè)節(jié)點(diǎn)就劃分到同一個(gè)階段剿另,而分到這兩個(gè)節(jié)點(diǎn)對(duì)應(yīng)行為的work node就可以自己獨(dú)立完成所有行為,不用管其他work node贬蛙;如果兩個(gè)節(jié)點(diǎn)之間有數(shù)據(jù)shuffle雨女,那么這個(gè)兩個(gè)節(jié)點(diǎn)就劃分到不同階段,對(duì)應(yīng)的所有work node就只能保證都完成節(jié)點(diǎn)1行為速客,shuffle數(shù)據(jù)戚篙,接著完成節(jié)點(diǎn)2行為。
??最后了解下RDD的優(yōu)勢(shì)和不能做的工作:
RDD是Spark的核心溺职,RDD的關(guān)鍵優(yōu)勢(shì)在于避免數(shù)據(jù)頻繁寫入磁盤岔擂。傳統(tǒng)MapReduce一個(gè)很大的問(wèn)題是不斷將中間結(jié)果寫入磁盤位喂,這就帶來(lái)了IO開銷和序列化反序列化開銷。而RDD會(huì)將中間結(jié)果保存在內(nèi)存中乱灵,從而節(jié)約大量開銷塑崖。RDD也是數(shù)據(jù)的抽象,我們只需要知道讀入的數(shù)據(jù)是RDD痛倚,而實(shí)際上數(shù)據(jù)會(huì)被分成讀個(gè)分區(qū)保存不同的work node上规婆,但我們不用關(guān)注這些底層細(xì)節(jié)。RDD只能完成粗粒度的數(shù)據(jù)操作(RDD對(duì)所有數(shù)據(jù)一起做操作蝉稳,不能只對(duì)部分?jǐn)?shù)據(jù)做針對(duì)性操作)抒蚜,RDD不支持細(xì)粒度數(shù)據(jù)修改,因此不太適合需要頻繁更新部分?jǐn)?shù)據(jù)的場(chǎng)景(比如網(wǎng)頁(yè)爬蟲的數(shù)據(jù)更新)耘戚。