使用Broadcast變量與map類算子實現join操作,進而完全規避掉shuffle類的操作

概述

有的時候,我們可能會遇到大數據計算中一個最棘手的問題——數據傾斜,此時Spark作業的性能會比期望差很多。數據傾斜調優,就是使用各種技術方案解決不同類型的數據傾斜問題,以保證Spark作業的性能。該篇博客參考美團的spark高級版,使用scala代碼進行簡單的模擬。

方案適用場景

在對RDD使用join類操作,或者是在Spark SQL中使用join語句時,而且join操作中的一個RDD或表的數據量比較小(比如幾百M或者一兩G),比較適用此方案。

方案實現思路

不使用join算子進行連接操作,而使用Broadcast變量與map類算子實現join操作,進而完全規避掉shuffle類的操作,徹底避免數據傾斜的發生和出現。將較小RDD中的數據直接通過collect算子拉取到Driver端的內存中來,然後對其創建一個Broadcast變量;接着對另外一個RDD執行map類算子,在算子函數內,從Broadcast變量中獲取較小RDD的全量數據,與當前RDD的每一條數據按照連接key進行比對,如果連接key相同的話,那麼就將兩個RDD的數據用你需要的方式連接起來。

方案實現原理

普通的join是會走shuffle過程的,而一旦shuffle,就相當於會將相同key的數據拉取到一個shuffle read task中再進行join,此時就是reduce join。但是如果一個RDD是比較小的,則可以採用廣播小RDD全量數據+map算子來實現與join同樣的效果,也就是map join,此時就不會發生shuffle操作,也就不會發生數據傾斜。具體原理如下圖所示。

方案優點

對join操作導致的數據傾斜,效果非常好,因爲根本就不會發生shuffle,也就根本不會發生數據傾斜。

方案缺點

適用場景較少,因爲這個方案只適用於一個大表和一個小表的情況。畢竟我們需要將小表進行廣播,此時會比較消耗內存資源,driver和每個Executor內存中都會駐留一份小RDD的全量數據。如果我們廣播出去的RDD數據比較大,比如10G以上,那麼就可能發生內存溢出了。因此並不適合兩個都是大表的情況。

如果對於hive中的map join熟悉的同學看這幅圖應該很好理解,所以建議大家看看hive中的map join原理,進行對比學習。

這裏寫圖片描述

代碼部分
import org.apache.spark.{SparkConf, SparkContext}

object BroadCast {

  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("BroadCast").setMaster("local[2]")
    val sc=new SparkContext(conf)

    val smallRDD=sc.parallelize(Array(
      ("1","zhangsan"),
      ("2","lisi"),
      ("3","wangwu")
    )).collectAsMap()

    val smallBroadCast=sc.broadcast(smallRDD)

    val bigRDD=sc.parallelize(Array(
      ("1","school1","male"),
      ("2","school2","female"),
      ("3","school3","male"),
      ("4","school4","male"),
      ("5","school5","female")
    )).map(x=>(x._1,x))

    val broadCastValue=smallBroadCast.value

     bigRDD.mapPartitions(partitions=>{

       for ((key,value)<-partitions
         if (broadCastValue.contains(key)))
         yield(key,broadCastValue.getOrElse(key,""),value._2,value._3)

     }).collect().foreach(println)

    /** 結果
      * (1,zhangsan,school1,male)
      * (2,lisi,school2,female)
      * (3,wangwu,school3,male)
      */

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