一、廣播變量和累加器
1.1、廣播變量
(1)廣播變量使用
val conf = new SparkConf()
conf.setMaster("local").setAppName("brocast")
val sc = new SparkContext(conf)
val list = List("hello xasxt")
val broadCast = sc.broadcast(list)
val lineRDD = sc.textFile("./words.txt")
lineRDD.filter { x => broadCast.value.contains(x) }.foreach { println}
sc.stop()
(2)注意事項
- 能不能將一個RDD使用廣播變量廣播出去?
不能,因爲RDD是不存儲數據的。可以將RDD的結果廣播出去。
- 廣播變量只能在Driver端定義,不能在Executor端定義。
- 在Driver端可以修改廣播變量的值,在Executor端無法修改廣播變量的值。
1.2、累加器
(1)累加器的使用
val conf = new SparkConf()
conf.setMaster("local").setAppName("accumulator")
val sc = new SparkContext(conf)
val accumulator = sc.accumulator(0)
sc.textFile("./words.txt").foreach { x =>{accumulator.add(1)}}
println(accumulator.value)
sc.stop()
(2)注意事項
- 累加器在Driver端定義賦初始值,累加器只能在Driver端讀取,在Excutor端更新。
二、Master HA
2.1、Master的高可用原理
Standalone集羣只有一個Master,如果Master掛了就無法提交應用程序,需要給Master進行高可用配置,Master的高可用可以使用fileSystem(文件系統)和zookeeper(分佈式協調服務)。
fileSystem只有存儲功能,可以存儲Master的元數據信息,用fileSystem搭建的Master高可用,在Master失敗時,需要我們手動啓動另外的備用Master,這種方式不推薦使用。
zookeeper有選舉和存儲功能,可以存儲Master的元素據信息,使用zookeeper搭建的Master高可用,當Master掛掉時,備用的Master會自動切換,推薦使用這種方式搭建Master的HA。
三、SparkShuffle
3.1、SparkShuffle介紹
(1)SparkShuffle概念
reduceByKey會將上一個RDD中的每一個key對應的所有value聚合成一個value,然後生成一個新的RDD,元素類型是<key,value>對的形式,這樣每一個key對應一個聚合起來的value。
問題:聚合之前,每一個key對應的value不一定都是在一個partition中,也不太可能在同一個節點上,因爲RDD是分佈式的彈性的數據集,RDD的partition極有可能分佈在各個節點上。
如何聚合?
– Shuffle Write:上一個stage的每個map task就必須保證將自己處理的當前分區的數據相同的key寫入一個分區文件中,可能會寫入多個不同的分區文件中。
– Shuffle Read:reduce task就會從上一個stage的所有task所在的機器上尋找屬於己的那些分區文件,這樣就可以保證每一個key所對應的value都會匯聚到同一個節點上去處理和聚合。
3.2、HashShuffleManager
(1)普通機制
執行流程:
- 每一個map task將不同結果寫到不同的buffer中,每個buffer的大小爲32K。buffer起到數據緩存的作用。
- 每個buffer文件最後對應一個磁盤小文件。
- reduce task來拉取對應的磁盤小文件。
總結:
- .map task的計算結果會根據分區器(默認是hashPartitioner)來決定寫入到哪一個磁盤小文件中去。ReduceTask會去Map端拉取相應的磁盤小文件。
- .產生的磁盤小文件的個數:M(map task的個數)*R(reduce task的個數)
存在的問題:
產生的磁盤小文件過多,會導致以下問題:
(a) 在Shuffle Write過程中會產生很多寫磁盤小文件的對象。
(b) 在Shuffle Read過程中會產生很多讀取磁盤小文件的對象。
(c) 在JVM堆內存中對象過多會造成頻繁的gc,gc還無法解決運行所需要的內存 的話,就會OOM。
(d) 在數據傳輸過程中會有頻繁的網絡通信,頻繁的網絡通信出現通信故障的可能性大大增加,一旦網絡通信出現了故障會導致shuffle file cannot find 由於這個錯誤導致的task失敗,TaskScheduler不負責重試,由DAGScheduler負責重試Stage。
(2)合併機制
總結:產生磁盤小文件的個數:C(core的個數)*R(reduce的個數)
3.3、SortShuffleManager
(1)普通機制
執行流程:
a) map task 的計算結果會寫入到一個內存數據結構裏面,內存數據結構默認是5M
b) 在shuffle的時候會有一個定時器,不定期的去估算這個內存結構的大小,當內存結構中的數據超過5M時,比如現在內存結構中的數據爲5.01M,那麼他會申請5.01*2-5=5.02M內存給內存數據結構。
c) 如果申請成功不會進行溢寫,如果申請不成功,這時候會發生溢寫磁盤。
d) 在溢寫之前內存結構中的數據會進行排序分區
e) 然後開始溢寫磁盤,寫磁盤是以batch的形式去寫,一個batch是1萬條數據,
f) map task執行完成後,會將這些磁盤小文件合併成一個大的磁盤文件,同時生成一個索引文件。
g) reduce task去map端拉取數據的時候,首先解析索引文件,根據索引文件再去拉取對應的數據。
總結:產生磁盤小文件的個數: 2*M(map task的個數)
(2)bypass機制
總結:
- .bypass運行機制的觸發條件如下:
shuffle reduce task的數量小於spark.shuffle.sort.bypassMergeThreshold的參數值。這個值默認是200。
- .產生的磁盤小文件爲:2*M(map task的個數)
3.4、Shuffle文件尋址
流程:
a) 當map task執行完成後,會將task的執行情況和磁盤小文件的地址封裝到MpStatus對象中,通過MapOutputTrackerWorker對象向Driver中的MapOutputTrackerMaster彙報。
b) 在所有的map task執行完畢後,Driver中就掌握了所有的磁盤小文件的地址。
c) 在reduce task執行之前,會通過Excutor中MapOutPutTrackerWorker向Driver端的MapOutputTrackerMaster獲取磁盤小文件的地址。
d) 獲取到磁盤小文件的地址後,會通過BlockManager連接數據所在節點,然後通過BlockTransferService進行數據的傳輸。
e) BlockTransferService默認啓動5個task去節點拉取數據。默認情況下,5個task拉取數據量不能超過48M。
(1)MapOutputTracker
MapOutputTracker是Spark架構中的一個模塊,是一個主從架構。管理磁盤小文件的地址。
- MapOutputTrackerMaster是主對象,存在於Driver中。
- MapOutputTrackerWorker是從對象,存在於Excutor中。
(2)BlockManager
BlockManager塊管理者,是Spark架構中的一個模塊,也是一個主從架構。
- BlockManagerMaster,主對象,存在於Driver中。
BlockManagerMaster會在集羣中有用到廣播變量和緩存數據或者刪除緩存數據的時候,通知BlockManagerSlave傳輸或者刪除數據。
- BlockManagerSlave,從對象,存在於Excutor中。
(3)BlockManagerSlave會與BlockManagerSlave之間通信。
- 無論在Driver端的BlockManager還是在Excutor端的BlockManager都含有三個對象:
- DiskStore:負責磁盤的管理。
- MemoryStore:負責內存的管理。
- BlockTransferService:負責數據的傳輸。