spark學習

總是學了就忘記,spark都學了幾遍了  總是深入不進去  唉  頭疼  這裏再次學習一遍  誰有更好的深入學習spark的方法給推薦推薦

面試了大數據,盤點幾個被問到的問題: 

    spark一定會把中間結果放在內存嗎?當然不是  可以是內存,也可以是磁盤  

    spark包括work和master   work和master之間的溝通通過網絡RPC進行交流溝通

拷貝到其他節點 for i in {5..7}; do scp -r /bigdata/spark/conf/spark-env.sh node-$i:$PWD; done

    spark是移動計算,而不移動數據   因爲大量數據移動成本大 

   spark是Scala 編寫  spark包本身有Scala編譯器和庫  但spark是運行在jvm上的  需要安裝jdk

  

利用zookeeper實現高可用集羣   zookeeper用來1選舉 2保存活躍的master信息 3 保存worker的資源信息和資源使用情況(爲了故障切換轉移)  在env.sh中添加export SPARK_DAEMON_JAVA_OPTS="-Dspark .deploy.recoveryMode=ZOOKEEPER xxxzookeeper相關信息"   高可用的spark需要手動啓動另一個(standby)spark-master  並不會隨着spark-all.sh 啓動master

 

一直搞不懂spark進程之間的關係   下面來理一下:

提交任務的機器(Driver)(spark-submit提交jar包的那個) 有SparkSubmit進程,有CoarseGrainedExecutorBackend(這個是executor,即worker的哦哦用來執行任務的進程),Worker進程(worker機器所在)     任務執行完成後  Executor進程會釋放    jps不在擁有Executor進程

 

在沒有集羣的時候  master會負責資源調度  保存worker資源情況  根據客戶端submit要求分配資源,即master和worker進行rpc通信,然後worker進程啓動executor(CoarseGrainedExecutorBackend),將分區參數傳遞過去

真正的計算邏輯是在driver端(submit端),生成task,然後通過網絡發送給各個executor進行執行。executor啓動後會主動連接driver,然後driver纔開始生成task。兩者之間的通信當然是通過master到worker進而知道的executor在哪裏

 

yarn和spark的stondalone對比

resourcemanager     對應  Master  都用來管理子節點和資源調度,接收任務請求

nodeManager         對應    Worker  管理當前節點,並管理子進程

yarnchild                對應      executor  用來運行真正的計算邏輯

applicationMaster用來管理yarnchild,,決定map reduce運行在哪一個yarnchild

yarn還有client用來提交任務         這兩個綜合起來相當於spark的SparkSubmit (提交app,管理度任務的executor並將task提交到executor)

RDD是彈性分佈式數據集,rdd並不存儲真正的數據,只是一個抽象,對rdd操作,會在driver端轉換成task,下發到executor計算分在多臺集羣上的數據

rdd是一個代理,對代理進行操作,會生成task幫助你計算,操作這個代理就像操作本地集合一樣方便

RDD有分區,是通過內部進行指定    分區裏面記錄的是位置變量(以後要讀取哪部分數據),生成的task交給executor,每個分區交給一個task去執行 ,然後task讀取數據去執行相應的操作   

aggregate方法,aggregate(0)(_+_ , _+_)   聚合操作,執行操作,每個分區分別執行,返回的順序不一定有序

aggregateByKey(0)(_+_ , _+_) 每個分區局部相加  再全部相加   假如說原RDD(pairRdd)有兩個分區,經過轉換後變成shuffledEdd(也有兩個分區,但分區內容是shuffle後的)

reduceByKey(_+_)

countByKey()

task在executor運算完成後,收集最終的數據到driver端   現在如果收集數據到redis  mysql 或者hbase,那麼不應該先collect收集數據到driver端,因爲數據量過大,容易使得driver端崩潰  

Rdd 的map方法,真正的在executor中執行的時候,是一條一條的將數據拿出來處理

foldByKey()

filter()

action:

rdd.collectAsMap()    

foreach(e =>println(e*100))  一條一條的拿(一條一條的執行function)

foreachPartition()   每個分區拿(一個分區執行一個function)

combineByKey(x=>x,(m:int,n:int)=>m+n, (a:Int,b:Int)=>a+b)   (m+n 是分區聚合  a+b 是全局聚合,key 保持不變,對value操作,最後生成shuffledRdd)

 

Spark執行流程:

這個圖雖然是到處都有   但真的很重要  理解他  記住他  spark基礎就完全ok了

1構建DAG(所謂的DAG就是描述的一個個RDD的轉換過程)(開始通過SparkContext創建RDD,結束調用runJob(也就是觸發action)就是一個完整的DAG過程了)(有多少個DAG,取決於觸發了多少次action)

2將DAG切分成stage(DAGSheduler)(切分的依據是shuffle),將stage中生成的Task以taskset的形式給TaskSheduler    將多臺機器上具有相同屬性的數據聚合到一臺機器上:shuffle    如果有shuffle,那麼就意味着前面階段產生結果後,才能執行下一個階段,下一個階段要依賴上一個階段的數據,在同一個stage中,會有多個算子,我們稱其爲pipeline

shuffle的含義:父RDD的一個分區中的數據如果給了子RDD中的多個分區(只要存在這種可能,例如款依賴時候如groupbyKey,他也有可能前一個步驟分區全部到下一個步驟的一個分區,但他可能分配到分多個分區,那麼也是shuffle),就是shuffle

寬依賴(shuffle)   窄依賴      

rdd1=sc.parallelize(List(("tom",1),("ketty",2),("tom",2)))  這個過程是把一個list shuffle到

不同分區的過程,所以也被分成一個stage

當然並不是所有的join都是寬依賴   如果前面的rdd數據比較規整  不需要shuffle到不同的分區 那麼就是窄依

然後執行完第一個階段後會執行第二個階段的task,同樣是driver端生產task  然後序列化,網絡傳輸到executor端進行反序列化,然後封裝成Runnable實現放到線程池進行處理

 

對RDD操作實際上是對分區進行操作 ,分區再生成task到executor執行操作

 

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