1. 程式人生 > >spark調優----廣播變數

spark調優----廣播變數

廣播變數
       在Spark Application中,經常會使用到一個共享變數,眾所周知的,Spark是一個平行計算框架,對於這個變數,每一個executor的task在訪問它的時候,都會去拷貝一份副本去使用。如下圖所示:

圖一


       1.對於這種預設方式,它會極大的系統的記憶體,我們可以假設一個叢集中有1024個task,這個共享變數大小假設為1M,那麼就會去複製1024份到叢集上去,這樣就會有1個G的資料在網路中傳輸,並且系統需要耗費1G記憶體去為這些副本分配空間,這樣對於系統有什麼影響呢?
       2.如果系統記憶體不足,RDD持久化的時候無法在記憶體中持久化,需要持久化到磁碟中,那麼後續的操作會因為頻繁的磁碟IO使得速度變慢,效能下降,當task中建立物件時,發現堆中記憶體不足,那麼就需要進行GC操作,進行GC的時候,會導致工作執行緒暫停,如果記憶體嚴重不足,頻繁的GC對於Spark作業的速度的影響是可想而知的
解決方法:


       針對這個情況我們可以使用Broadcast,將這種每個task需要用到的共享變數廣播出去。
       從上面的圖中可以看到,當每一個task需要使用這個變數的時候都會拷貝一份。如果使用廣播變數,首先該廣播變數會拷貝一份副本到Driver中,當每一個executor的task使用到該變數時,首先會去每個executor的BlockManager中去檢查是否有該變數的副本,如果沒有,接著會去Driver中去拷貝一份副本到BlockManager中,然後供該executor中的每一個task使用,到下一個executor的task需要使用這個變數時,它的BlockManager可以去Driver中拷貝副本,也可以去距離比較近的executor的BlockManager中去拷貝。(每一個executor中的BlockManager的作用是負責管理每一個executor對應的記憶體和磁碟的資料。)其原理圖如上所示
   

圖二


       在預設情況下,如果是1024個task需要消耗1G記憶體,但是如果我們有50個executor來平分這些task,那麼只需要50個副本即可,總共消耗了50M記憶體,那麼在記憶體的消耗了節省了大約20倍。而且副本的複製有時不需要從Driver拷貝,而是從其他executor中拷貝,那麼,網路 傳輸帶來的效能消耗也會小很多,可想而知,使用廣播變數可以節省很多記憶體,從而使得效能顯著提升
廣播方法
      比如我們的共享變數是一個map型別的變數,我們可以使用Spark上下文來建立廣播變數:
      Broadcast<Map<String>> broadcast=sc.broadcast(map);1
      在task中使用的時候可以使用value方法或者getValue方法來獲取它的值:
      Map<String> map=broadcast.value;