第二十三記·Spark Core詳解

XY個人記

Apache Spark是專爲大規模數據處理而設計的快速通用的計算引擎  。現在形成一個高速發展應用廣泛的生態系統。

官網地址:http://spark.apache.org/

Spark,擁有Hadoop MapReduce所具有的優點;但不同於MapReduce的是——Job中間輸出結果可以保存在內存中,從而不再需要讀寫HDFS,因此Spark能更好地適用於數據挖掘與機器學習等需要迭代的MapReduce的算法。 

Spark 是在 Scala 語言中實現的,它將 Scala 用作其應用程序框架。與 Hadoop 不同,Spark 和 Scala 能夠緊密集成,其中的 Scala 可以像操作本地集合對象一樣輕鬆地操作分佈式數據集。
           儘管創建 Spark 是爲了支持分佈式數據集上的迭代作業,但是實際上它是對 Hadoop 的補充,可以在 Hadoop 文件系統中並行運行。通過名爲 Mesos 的第三方集羣框架可以支持此行爲。Spark 由加州大學伯克利分校 AMP 實驗室 (Algorithms, Machines, and People Lab) 開發,可用來構建大型的、低延遲的數據分析應用程序。

 

性能特點

    1.Speed(快速)
        內存計算下,Spark 比 Hadoop 快100倍。
    2.Ease of Use(易用性)
        可用多種語言:Java, Scala, Python, R, and SQL
        Java開發
            好處:對於大數據大型項目來說,涉及到HBase、Hive、Flume等等,有利於整合
            壞處:代碼量比較大,代碼不優雅
        scala開發:Spark本身源碼就是scala,兼容性好,代碼更簡潔

    3.Generality(通用)
        整合:spark sql、spark streaming、MLlib、GraphX
    4.Runs Everywhere(在任何平臺運行)
        Spark runs on Hadoop, Apache Mesos, Kubernetes, standalone, or in the cloud
        國內:一般選擇在yarn上運行
        國外:一般選擇Mesos運行

Spark MapReduce 比較

MapReduce Spark
數據存儲結構:磁盤hdfs文件系統的split 使用內存構建彈性分佈式數據集RDD,對數據進行 運算和cache
編程範式:Map + Reduce DAG(有向無環圖):Transformation + action
計算中間數據落磁盤,io及序列化、反序列化代 價大 計算中間數據在內存中維護,存取速度是磁盤的 多個數量級
Task以進程的方式維護,任務啓動就有數秒 Task以線程的方式維護,對小數據集的讀取能達到 亞秒級的延遲

Spark的版本差別
    Spark1.6
        出現Dataset的概念,與DataFrame兩個概念
        程序的主入口SparkContext(sc)
        
    Spark2.0+
        統一了Dataset和DataFrame:    type DataFrame = Dataset[Row]
        程序的主入口變成SparkSession(spark),用於替換統一HiveContext、SQLContext
        累加器API更簡單更高性能

spark基本工作原理:分佈式    基於內存    迭代式

 

RDD:spark基本抽象

Resilient(彈性) Distributed(分佈式) Dataset(數據集)彈性分佈式數據集, 是分佈式內存的一個抽象概念,RDD提供了一種高度受限的共享內存模型,即RDD是隻讀的記錄分區的集合,只能通過在其他RDD執行確定的轉換操作(如map、join和group by)而創建,然而這些限制使得實現容錯的開銷很低。

RDD可以抽象的代表一個HDFS文件,RDD是以分區的形式存在,每個分區存在不同的節點上。分區的數據默認放在內存上,如果某個文件的大小超過了它所在節點存儲的大小,它會把存放不下的數據存儲在當前節點的內存中,會自動進行內存和磁盤的切換。

    數據集:內部是一個數據集合
    分佈式:數據分區存在,並且存放在spark集羣的不同的節點上
    彈性:
        -1. 自動進行內存和磁盤存儲的切換(用戶只需要關注RDD的計算處理、操作) RDD的分區的數據默認是放在內存上
        -2. 基於血統(依賴)的高效容錯性  RDD1  經過轉換生成  RDD2
        -3. DRR的最小單位Task失敗,自動重試機制

RDD特點:
    RDD裏面的數據是不可變的並且分區存在,每次調用RDD的API,會生成新的RDD,對舊的RDD的數據不會發生變化

RDD的五大特性
    *  - A list of partitions(分區列表)
    *  - A function for computing each split(每個分區都有一個計算函數)
    *  - A list of dependencies on other RDDs (依賴於其他RDD的一個列表)
    *  - Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
       (對於key-value形式的RDD有一個分區器) key-value形式你可以理解爲二元組形式的RDD[(String,Int)]
    *  - Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
        (每個分區都有一個分區位置列表)

 

RDD 的兩種算子

1、Transformation(轉換):Transformation 是一個RDD到另一個RDD,延遲執行
2、Ation(執行):是一個RDD到一個結果,立即執行

Transformation具體內容

1、map(func) : 
                        返回一個新的分佈式數據集,由每個原元素經過func函數轉換後組成。

2、filter(func) :  
                        返回一個新的數據集,由經過func函數後返回值爲true的原元素組成 。

3、flatMap(func) :  
                        類似於map,但是每一個輸入元素,會被映射爲0到多個輸出元素(因此,func函數的返回值是一個Seq,而不是單一元素)。

4、sample(withReplacement, frac, seed) :  
                        根據給定的隨機種子seed,隨機抽樣出數量爲frac的數據。

5、union(otherDataset) :  
                        返回一個新的數據集,由原數據集和參數聯合而成。

6、groupByKey([numTasks]) :  
                        在一個由(K,V)對組成的數據集上調用,返回一個(K,Seq[V])對的數據集。注意:默認情況下,使用8個並行任務進行分組,你可以傳入numTask可選參數,根據數據量設置不同數目的Task。

7、reduceByKey(func, [numTasks]) :  
                        在一個(K,V)對的數據集上使用,返回一個(K,V)對的數據集,key相同的值,都被使用指定的reduce函數聚合到一起。和groupbykey類似,任務的個數是可以通過第二個可選參數來配置的。

8、join(otherDataset, [numTasks]) :  
                        在類型爲(K,V)和(K,W)類型的數據集上調用,返回一個(K,(V,W))對,每個key中的所有元素都在一起的數據集。

9、groupWith(otherDataset, [numTasks]) :  
                        在類型爲(K,V)和(K,W)類型的數據集上調用,返回一個數據集,組成元素爲(K, Seq[V], Seq[W]) Tuples。

10、cartesian(otherDataset) :  
                        笛卡爾積。但在數據集T和U上調用時,返回一個(T,U)對的數據集,所有元素交互進行笛卡爾積。


Actions具體內容

1、reduce(func) :  
                        通過函數func聚集數據集中的所有元素。Func函數接受2個參數,返回一個值。這個函數必須是關聯性的,確保可以被正確的併發執行。

2、collect() :  
                        在Driver的程序中,以數組的形式,返回數據集的所有元素。這通常會在使用filter或者其它操作後,返回一個足夠小的數據子集再使用,直接將整個RDD集Collect返回,很可能會讓Driver程序OOM。

3、count() : 
                        返回數據集的元素個數。

4、take(n) : 
                        返回一個數組,由數據集的前n個元素組成。注意,這個操作目前並非在多個節點上,並行執行,而是Driver程序所在機器,單機計算所有的元素內存壓力會增大,需要謹慎使用。

5、first() : 
                        返回數據集的第一個元素(類似於take(1))。

6、saveAsTextFile(path) :  
                        將數據集的元素,以textfile的形式,保存到本地文件系統,hdfs或者任何其它hadoop支持的文件系統。Spark將會調用每個元素的toString方法,並將它轉換爲文件中的一行文本。

7、saveAsSequenceFile(path) :  
                        將數據集的元素,以sequencefile的格式,保存到指定的目錄下,本地系統,hdfs或者任何其它hadoop支持的文件系統。RDD的元素必須由key-value對組成,並都實現了Hadoop的Writable接口,或隱式可以轉換爲Writable(Spark包括了基本類型的轉換,例如Int,Double,String等等)。

8、foreach(func) :  
                        在數據集的每一個元素上,運行函數func。這通常用於更新一個累加器變量,或者和外部存儲系統做交互。

 

Spark應用的結構

    Driver + Executors

    Driver:相當於MapReduce中ApplicationMaster,運行SparkContext上下文、SparkContext進行初始化的地方(JVM)、進行RDD的初始化、Task運行的資源申請、調度的地方。 一般認爲就是main運行的地方
    Executors:具體的Task運行的地方,一個executor可以運行多個Task任務,一個spark應用可以有多個Executor

    進程
        local模式
        Driver和Executor運行在同一個進程(SparkSubmit),以線程的方式進行區分的

        集羣模式(standalone、yarn、mesos)
        Driver:
            SparkSubmit
        Executor:(有幾個Executor就會有幾個CoarseGrainedExecutorBackend進程)
            CoarseGrainedExecutorBackend

        spark-shell底層運行的就是spark-submit命令,spark-submit底層運行spark-class

    Application(每個應用都有Driver+Executors)一個應用包含多個job

    如下圖所示:RDD的action類型的API一旦觸發就會產生一個job 一個Job裏面包含多個Stage
                         stage0    有shuffle操作就會劃分stage
                         一個Stage裏面可以包含多個Task,Task就是最小的運行單位,是在executor處理對應分區數據的線程

1、Application
         application(應用)其實就是用spark-submit提交的程序。比方說spark examples中的計算pi的SparkPi。一個application通常包含三部分:從數據源(比方說HDFS)取數據形成RDD,通過RDD的transformation和action進行計算,將結果輸出到console或者外部存儲(比方說collect收集輸出到console)。

2、Driver
         Spark中的driver感覺其實和yarn中Application Master的功能相類似。主要完成任務的調度以及和executor和cluster manager進行協調。有client和cluster聯衆模式。client模式driver在任務提交的機器上運行,而cluster模式會隨機選擇機器中的一臺機器啓動driver。從spark官網截圖的一張圖可以大致瞭解driver的功能。

3、Job
         Spark中的Job和MR中Job不一樣不一樣。MR中Job主要是Map或者Reduce Job。而Spark的Job其實很好區別,一個action算子就算一個Job,比方說count,first等。

4、Task
         Task是Spark中最新的執行單元。RDD一般是帶有partitions的,每個partition的在一個executor上的執行可以任務是一個Task。

5、Stage
         Stage概念是spark中獨有的。一般而言一個Job會切換成一定數量的stage。各個stage之間按照順序執行。至於stage是怎麼切分的,首選得知道spark論文中提到的narrow dependency(窄依賴)和wide dependency( 寬依賴)的概念。其實很好區分,看一下父RDD中的數據是否進入不同的子RDD,如果只進入到一個子RDD則是窄依賴,否則就是寬依賴。寬依賴和窄依賴的邊界就是stage的劃分點

Stage的切分規則從後往前,遇到寬依賴就切割stage。

Stage計算模式:pipeline管道計算模式,pipeline只是一種計算思想,模式。

備註:圖中幾個理解點:

   1、Spark的pipeLine的計算模式,相當於執行了一個高階函數f3(f2(f1(textFile))) !+!+!=3 也就是來一條數據然後計算一條數據,把所有的邏輯走完,然後落地,準確的說一個task處理遺傳分區的數據 因爲跨過了不同的邏輯的分區。而MapReduce是 1+1=2,2+1=3的模式,也就是計算完落地,然後在計算,然後再落地到磁盤或內存,最後數據是落在計算節點上,按reduce的hash分區落地。所以這也是比Mapreduce快的原因完全基於內存計算

   2、管道中的數據何時落地:shuffle write的時候,對RDD進行持久化的時候。

   3.   Stage的task並行度是由stage的最後一個RDD的分區數來決定的 。一般來說,一個partiotion對應一個task,但最後reduce的時候可以手動改變reduce的個數,也就是分區數,即改變了並行度。例如reduceByKey(XXX,3),GroupByKey(4),union由的分區數由前面的相加。

   4.、如何提高stage的並行度:reduceBykey(xxx,numpartiotion),join(xxx,numpartiotion)

 

Client和Cluster兩種運行模式的工作流程

Client模式下,Driver進程會在當前客戶端啓動,客戶端進程一直存在直到應用程序運行結束

工作流程如下:
1.啓動master和worker . worker負責整個集羣的資源管理,worker負責監控自己的cpu,內存信息並定時向master彙報
2.在client中啓動Driver進程,並向master註冊
3.master通過rpc與worker進行通信,通知worker啓動一個或多個executor進程
4.executor進程向Driver註冊,告知Driver自身的信息,包括所在節點的host等
5.Driver對job進行劃分stage,並對stage進行更進一步的劃分,將一條pipeline中的所有操作封裝成一個task,併發送到向自己註冊的executor
進程中的task線程中執行
6.應用程序執行完成,Driver進程退出

cluster模式下,Driver進程將會在集羣中的一個worker中啓動,而且客戶端進程在完成自己提交任務的職責後,就可以退出,而不用等到應用程序執行完畢

工作流程如下:
1.在集羣的節點中,啓動master , worker進程,worker進程啓動成功後,會向Master進行註冊。
2.客戶端提交任務後,ActorSelection(master的actor引用),然後通過ActorSelection給Master發送註冊Driver請求(RequestSubmitDriver)
3.客戶端提交任務後,master通知worker節點啓動driver進程。(worker的選擇是隨意的,只要worker有足夠的資源即可)
driver進程啓動成功後,將向Master返回註冊成功信息
4.master通知worker啓動executor進程
5.啓動成功後的executor進程向driver進行註冊
6.Driver對job進行劃分stage,並對stage進行更進一步的劃分,將一條pipeline中的所有操作封裝成一個task,併發送到向自己註冊的executor
進程中的task線程中執行
7.所有task執行完畢後,程序結束

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章