在分享中,陳超(@CrazyJvm,ChinaScala)首先簡(jiǎn)短的介紹了Spark社區(qū)在2014年的發(fā)展:目前Spark的發(fā)布版本是1.2,整個(gè)2014年Spark共發(fā)布了3個(gè)主要版本——1.0、1.1、1.2。隨后,陳超對(duì)Spark生態(tài)圈進(jìn)行了詳細(xì)的分析: Spark:What & Why? Spark是一個(gè)非???,并且普適性非常強(qiáng)的一個(gè)大數(shù)據(jù)處理引擎。談到Spark,首先就是一些常見(jiàn)特性:速度快、易用、通用和兼容Hadoop。首先通用,Spark可以支撐批處理、流計(jì)算、圖計(jì)算、機(jī)器學(xué)習(xí)等眾多應(yīng)用場(chǎng)景;其次,與Hadoop良好的兼容。鑒于大多數(shù)的企業(yè)仍選用HDFS來(lái)存數(shù)據(jù),Spark的設(shè)計(jì)與HDFS有著非常好的兼容性——假如數(shù)據(jù)存儲(chǔ)在HDFS,那么不做任何數(shù)據(jù)遷移工作就可以直接使用Spark。 Spark vs. Hadoop
對(duì)于為什么要選擇Spark,如上圖所示,陳超從迭代計(jì)算和HDFS同批數(shù)據(jù)的多維度查詢(xún)兩個(gè)方面將之與Hadoop進(jìn)行了對(duì)比: 迭代計(jì)算。在這個(gè)場(chǎng)景下,Hadoop需要多次讀寫(xiě)HDFS(磁盤(pán)),造成了大量的IO和序列化、反序列化等額外開(kāi)銷(xiāo)。此外,每次寫(xiě)HDFS都需要寫(xiě)入3份,因此造成了備份方面的開(kāi)銷(xiāo)。 HDFS同批數(shù)據(jù)的多維度查詢(xún)。對(duì)HDFS同一批數(shù)據(jù)做成百或上千維度查詢(xún)時(shí),Hadoop每次做一個(gè)獨(dú)立的query,也就是每次都要從磁盤(pán)讀取這個(gè)數(shù)據(jù)。因?yàn)槊看味紡拇疟P(pán)中讀取同一組數(shù)據(jù),效率顯然可以繼續(xù)提高。 而在這兩種場(chǎng)景中,Spark可以使用內(nèi)存緩存中間/常用數(shù)據(jù),從而在避免磁盤(pán)IO開(kāi)銷(xiāo)的同時(shí),還將大幅度提高性能。 Why Spark is so Fast? Spark一直以快速著稱(chēng),那么除下之前所說(shuō)的內(nèi)存,又是什么特性讓Spark可以如此之快?在這里,陳超提到了DAG(有向無(wú)環(huán)圖,下文詳細(xì)介紹)、Thread Model(線(xiàn)程模型)和Optimization(比如延遲調(diào)度)3個(gè)方面。 Thread Model。Hadoop基于進(jìn)程模型,每次啟動(dòng)一個(gè)task都需要新啟動(dòng)一個(gè)子JVM進(jìn)行計(jì)算,可能也會(huì)存在JVM Reuse,這里即使避開(kāi)JVM Reuse中存在的問(wèn)題不談,每次JVM啟動(dòng)時(shí)已經(jīng)造成了不菲的開(kāi)銷(xiāo)。而Spark在應(yīng)用程序啟動(dòng)時(shí)就啟動(dòng)了線(xiàn)程池,所以任務(wù)的啟動(dòng)開(kāi)銷(xiāo)非常小。 Optimization——延遲調(diào)度。當(dāng)任務(wù)下達(dá)到某臺(tái)主機(jī)時(shí),恰好該主機(jī)的計(jì)算資源(CPU、內(nèi)存等)已被耗盡,這個(gè)時(shí)候,Spark會(huì)采用延遲調(diào)度的機(jī)制,讓其等待一小會(huì),而不是將該臺(tái)主機(jī)上需要計(jì)算的數(shù)據(jù)通過(guò)網(wǎng)絡(luò)傳輸?shù)搅硗獾闹鳈C(jī)上。使用這個(gè)機(jī)制,在計(jì)算數(shù)據(jù)體積非常大時(shí),有著很大的優(yōu)勢(shì)。 也就是所謂的“讓計(jì)算跟著數(shù)據(jù)走,而不是數(shù)據(jù)跟著計(jì)算走”。 Spark解析 伯克利數(shù)據(jù)分析協(xié)議棧
其中包括:資源管理框架,Apache YARN、Apache Mesos;基于內(nèi)存的分布式文件系統(tǒng),Tachyon;隨后是Spark,更上面則是實(shí)現(xiàn)各種功能的系統(tǒng),比如機(jī)器學(xué)習(xí)MLlib庫(kù),圖計(jì)算GraphX,流計(jì)算Spark Streaming。再上面比如:SparkR,分析師的最?lèi)?ài);BlinkDB,我們可以強(qiáng)迫它幾秒鐘內(nèi)給我們查詢(xún)結(jié)果。 正是這個(gè)生態(tài)圈,讓Spark可以實(shí)現(xiàn)“one stack to rule them all”,它既可以完成批處理也可以從事流計(jì)算,從而避免了去實(shí)現(xiàn)兩份邏輯代碼。而整個(gè)Spark的理論基礎(chǔ)就是RDD: RDD的核心理念 RDD可以想象為一個(gè)個(gè)的partitions,退一步也可理解為一個(gè)非常大的List(1,2,....9),使用3個(gè)Partion分別保存這個(gè)List的3個(gè)元素,而每個(gè)partition(或者split)都會(huì)有一個(gè)函數(shù)去計(jì)算。同時(shí),RDD之間是可以相互依賴(lài)的。然后,可以為Key-value RDD指定partitioner, RDD中的每個(gè)split也都有各自的preferred location。 最后一個(gè)preferred locations,這個(gè)理念存在于當(dāng)下的眾多分布式系統(tǒng)中,也就是計(jì)算跟著數(shù)據(jù)走。通常情況下,轉(zhuǎn)移計(jì)算的時(shí)間遠(yuǎn)遠(yuǎn)小于轉(zhuǎn)移數(shù)據(jù)的時(shí)間。對(duì)于Hadoop來(lái)說(shuō),因?yàn)閿?shù)據(jù)在磁盤(pán)中,磁盤(pán)本地性通常達(dá)到了頂峰,而對(duì)于Spark來(lái)講,因?yàn)閿?shù)據(jù)(可以)保存在內(nèi)存中,所以?xún)?nèi)存本地性才具備最高優(yōu)先級(jí)。 運(yùn)行原理
上圖表述了Spark運(yùn)行原理:rdd1、rdd2、rdd3等等一直轉(zhuǎn)換到另外一個(gè)RDD。需要注意的是,這里面存在的是一個(gè)延遲的執(zhí)行,也就是轉(zhuǎn)換不會(huì)立刻執(zhí)行。Spark只會(huì)在元數(shù)據(jù)中記錄這個(gè)過(guò)程,但是不會(huì)真正的執(zhí)行,這個(gè)要注意一點(diǎn),只有在碰到action的時(shí)候才會(huì)真正的去執(zhí)行。這個(gè)時(shí)候需要注意的是,比如上圖RDD2所做的cache,這個(gè)操作同樣是lazy的,同樣在碰到action的時(shí)候才會(huì)執(zhí)行。就在這里,坑出現(xiàn)了,即使persist與cache使用的是相同的接口,但是unpersist卻是eager的。從1.1版本開(kāi)始,cache其實(shí)已經(jīng)有了更安全的做法,但是涉及過(guò)多內(nèi)核細(xì)節(jié),這里就不做多的解釋。 RDD的依賴(lài)性
narrow dependency和wide dependency是Spark中另外兩個(gè)重要的概念。對(duì)比后者,narrow dependency無(wú)論是在從容錯(cuò)上,還是在執(zhí)行效率上都占有優(yōu)勢(shì)。 ClusterManager:目前來(lái)講,在國(guó)內(nèi)采用率更大的顯然是YARN。 Cluster overview
Sparkcontext,寫(xiě)代碼時(shí)生成,并向ClusterManager請(qǐng)求資源。ClusterManager會(huì)負(fù)責(zé)連接到Worker Node取得資源,其中executor才是task的真正執(zhí)行者。這里有三個(gè)需要注意的點(diǎn):第一,ClusterManager是可插拔的,可以任意選擇;第二點(diǎn),因?yàn)閐river program需求發(fā)送任務(wù)給Worker Node,因此提交任何的地方不要離Worker Node特別遠(yuǎn)。第三點(diǎn)比較重要的一點(diǎn),每個(gè)應(yīng)用程序在每個(gè)Worker Node上都會(huì)有獨(dú)立的executor,并且不同應(yīng)用程序的executor(間)是不可以共享數(shù)據(jù)的。 PS:YARN通過(guò)Container來(lái)封裝資源,因此在YARN中Worker對(duì)應(yīng)的是Container。 調(diào)度
最初,Spark程序會(huì)隱式地建立一個(gè)邏輯上有向無(wú)環(huán)圖(DAG),隨后DAGScheduler會(huì)將DAG切分成一個(gè)個(gè)stage,隨后這些stage會(huì)被傳送給TaskSchedluer,之后再傳送給Worker上的excutor執(zhí)行。其中excutor會(huì)以多線(xiàn)程的模式執(zhí)行。 Shuffle 從理論上講,Spark Shuffle從未超過(guò)MapReduce,直到改完以后才OK。當(dāng)下,Shuffle使用的是基于PULL的模式,中間文件會(huì)寫(xiě)到磁盤(pán),同時(shí),在每個(gè)partition都會(huì)建立hash map。需要注意的是,在可以跨keys spill的同時(shí),主機(jī)內(nèi)存必須可以裝進(jìn)單key-value。 在監(jiān)控上,之前的版本中,只有當(dāng)一個(gè)任務(wù)結(jié)束時(shí),才可以收集這個(gè)任務(wù)的運(yùn)行數(shù)據(jù),這點(diǎn)在當(dāng)下的版本已被改進(jìn)。 生態(tài)系統(tǒng)簡(jiǎn)析 Spark Streaming:Spark Streaming實(shí)質(zhì)上仍然是批處理,但是把之前大的批處理拆為小的batch。同時(shí),當(dāng)下Spark Streaming已支持限流,當(dāng)流量很大時(shí),Spark可以擋住。此外,它還可以支持實(shí)時(shí)機(jī)器學(xué)習(xí)。在Spark Streaming中,數(shù)據(jù)丟失一般因?yàn)閮煞N情況——worker failure和driver failure。在之前版本中,可能會(huì)存在小部分的數(shù)據(jù)丟失,而在1.2版本發(fā)布后,reliable receiver模式保證了所有數(shù)據(jù)不會(huì)丟失,這點(diǎn)在Kafka的連接上非常適用。 MLlib:當(dāng)下的算法已經(jīng)非常豐富,包括分類(lèi)、聚類(lèi)、回歸、協(xié)同過(guò)濾、降維等等。ML Pipeline可以大幅度的減少開(kāi)發(fā)時(shí)間,它可以幫開(kāi)發(fā)者打通數(shù)據(jù)收集、數(shù)據(jù)清理、特征提取,模型訓(xùn)練,測(cè)試、評(píng)估、上線(xiàn)整個(gè)流程。 Graphx:在這里,Spark的優(yōu)勢(shì)是既能處理表視圖,也能處理圖視圖。 Spark SQL:Spark生態(tài)圈中最火的組件,目的很簡(jiǎn)單,用來(lái)支持SQL標(biāo)準(zhǔn)。對(duì)比Spark SQL,因?yàn)榛贛apReduce的進(jìn)程模型,Hive中存在許多一直未修復(fù)的多線(xiàn)程bug。值得一提的是,Spark SQL的貢獻(xiàn)者中,一半以上是華人。
Tachyon可以支撐幾乎所有框架 Tachyon:內(nèi)存分布式系統(tǒng),讓不同的Job或者框架分享數(shù)據(jù),從而繞過(guò)HDFS,以更快地速度執(zhí)行。同時(shí),它還可以避免任務(wù)失敗時(shí)的數(shù)據(jù)重算。最后,Tachyon可以讓系統(tǒng)避免多次GC。 SparkR:讓R語(yǔ)言調(diào)用Spark。原理是Spark Context通過(guò)JNI調(diào)用Java Spark Context,隨后通過(guò)Worker上的Excutor調(diào)用R的shell來(lái)執(zhí)行?,F(xiàn)在存在的問(wèn)題是,每次task執(zhí)行時(shí)都需要啟動(dòng)R shell,所以還亟待優(yōu)化。
BlinkDB,一個(gè)任性的數(shù)據(jù)庫(kù) BlinkDB:很任性的一個(gè)數(shù)據(jù)庫(kù),允許操作者帶著time bounds或者error bounds去查。原理是在原始數(shù)據(jù)上維護(hù)一組多維樣本,當(dāng)然其中還需要一個(gè)動(dòng)態(tài)的樣本選擇策略。 JobServer:提供了一個(gè)RESTful接口來(lái)提交和管理Apache Spark job、jars及job contexts,即Spark as a Service。 |
|
來(lái)自: 昵稱(chēng)22473147 > 《待分類(lèi)》