spark的broadcast理解

Broadcast(使用BroadcastManager管理)一般用於處理共享配置文件、常用的數據結構等;但Broadcast不適合存放太大數據,Broadcast不會內存溢出,因爲數據保存級別StoreageLevelMEMORY_AND_DISK模式。數據量大會造成網絡I/O和單點壓力大,因此,當數據量較大時不要使用broadcast,網絡成本較大,會適得其反。

廣播變量:實際上就是Driver端的變量通過Broadcast方法傳輸到Executor端,Executor端不能修改廣播變量的值,使用廣播變量是爲了減少Executor端的數據備份,減少Executor端的內存。

如:driver端有100個變量,如果不使用廣播變量的話,從driver端發給executor端有100個備份,使用了廣播變量,就會只有一個備份,從而可以減少executor端的內存。

注意:
        1).不能將RDD廣播出去,可以將RDD的結果廣播出去
        2).廣播變量在Driver定義,在Exector端不可改變,在Executor端不能定義。

private def writeBlocks(value: T): Int = {
// 在Driver中存儲廣播變量的副本,以便在Driver上運行任務,不是創建廣播變量值得副本
SparkEnv.get.blockManager.putSingle(broadcastId, value, StorageLevel.MEMORY_AND_DISK,
tellMaster = false)
//序列化數據對象,並拆分成多個數據塊
val blocks =TorrentBroadcast.blockifyObject(value, blockSize, SparkEnv.get.serializer, compressionCodec)
blocks.zipWithIndex.foreach { case (block, i) =>
//存儲數據塊到BlockManager
SparkEnv.get.blockManager.putBytes(BroadcastBlockId(id, "piece" + i),block,StorageLevel.MEMORY_AND_DISK_SER,tellMaster = true)
}blocks.length}

代碼:

object BroadcastTest {

  /**首次Broadcast變量在executor中反序列化,broadcast數據是從driver中拉取的,並存儲在executor的BlockManager中
    * */
  def main(args: Array[String]) {

    val blockSize = if (args.length > 2) args(2) else "4096"

    val spark: SparkSession = SparkSession
      .builder()
      .master("local[*]")
      .appName("Broadcast Test")
      .config("spark.broadcast.blockSize", blockSize)
      .getOrCreate()

    val sc = spark.sparkContext

    val slices = if (args.length > 0) args(0).toInt else 2
    val num = if (args.length > 1) args(1).toInt else 1000000

    val arr1 = (0 until num).toArray

    for (i <- 0 until 3) {
      println(s"Iteration $i")
      val startTime = System.nanoTime()
      val barr1 = sc.broadcast(arr1)
      val observedSizes = sc.parallelize(1 to 10, slices).map(_ => barr1.value.length)
      /**不能將RDD廣播出去,可以將RDD的結果(如rdd.collect)廣播出去;
        * 廣播變量在Driver定義,在Executor端不可改變,在Executor端不能定義*/
      observedSizes.collect().foreach(i => println(i))
      println("Iteration %d took %.0f milliseconds".format(i, (System.nanoTime - startTime) / 1E6))
    }

    spark.stop()
  }
}

 

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