spark 获取广播变量_spark-3 广播变量,累加器,持久化(Scala与Python版本对照)

持久化:

在spark里,多个rdd复用的时候建议对其持久化,这样就能只计算一次,如有必要还可以持久化两份,也就是所谓的双副本机制。(一般只建议用反序列内存或者序列内存,因为有时候去硬盘读的效果还不如重新计算)

广播变量:

rdd在task里运算,需要匹配一些外部变量的时候,就会去driver端拉取,如果变量过大,这时候就会消耗网络IO,同时每个task也会保存一份,在同一个execu上消耗了内存。可以通过广播变量将其从driver'端保存到每一个executor的内存中让task共享。(一般不建议超过1g)

累计器:

类似上诉,创建一个累加器,共享变量,注意该变量只能在driver端才能查看其存储的值(如scala的foreach里就不能用println查看)


scala版
package com.chen.spark

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext

object broadcast {
  def main(args:Array[String]):Unit = {
     val conf = new SparkConf()
         .setAppName("broadcast")
         .setMaster("local")
     val sc = new SparkContext(conf)
     
     /**
      * 广播变量
      * 当多个task需要调用外部非RDd变量时,需要每一个去走io到driver拉取,并且每个task都要一份
      * 广播之后,driver会将变量发送到每个executor内存中,对多core共用
      * 节省网络io和内存(尤其是变量较大时)
      */
     val factor = 2  
     val bc_factor =sc.broadcast(factor)
     
     val numlistRDD = sc.parallelize(Array(1, 2, 3, 4), 1)
     // 注意此处需要value函数来获取存储的值
     val num_mul_2 = numlistRDD.map( x => x * bc_factor.value)
     
     num_mul_2.foreach(x => println(x))
     println("############# broadcast #############")
     
     /**
      * 累加器
      * 效果大致类似,初始化一个值,来对他进行迭代操作
      * 注意:task只能对他累加,driver才能对他拉取并获取里面的结果
      */
     val num_accu = sc.accumulator(0)
     
     val intRDD = sc.parallelize(Array(1, 2, 3, 4, 5))
     //  通过内置函数add来累加
     intRDD.foreach( i => num_accu.add(i))
     
     // 驱动程序通过value来获取里面的结果
     println(num_accu.value)
     println("############# accumulator ########")
     
     sc.stop()
     
  }
 
}
Python版本
# -*- coding:utf-8 -*-
from pyspark import SparkConf
from pyspark import SparkContext


def CreateSparkContext():
    sparkConf = SparkConf() 
                .setAppName("transformation_py") 
                .set("spark.ui.showConsoleProgress", "false")
    sc = SparkContext(conf = sparkConf)    # 不同于scala,这里必须指定conf来传参
    print("master =" + sc.master)
    return sc

if __name__ == "__main__":
    sc = CreateSparkContext()
    
    kv_fruit = sc.parallelize([(1, "banana"), (2, "apple"),
                              (3, "grape"), (4, "orange")])
    # 下面要复用两次,所以这里实例了一下rdd缓存
    # scala老版本里只能链式调用,新版本未测试
    numlistRDD = sc.parallelize([1, 4, 2, 4, 3]).persist()
    
    num_accu = sc.accumulator(0)
    
    # 注意 在scala里我们是直接创建了一个非rdd变量
    # 这里我们是先创建了一个kv Rdd,然后将其转换为Python独有的dict
    fruitMap = kv_fruit.collectAsMap()
    bc_fruitMap = sc.broadcast(fruitMap)    # 是一个dict
    
    fruit = numlistRDD.map(lambda x: bc_fruitMap.value[x]).collect()
    print(fruit)
    print("########## broadcast ########")
    
    numlistRDD.foreach(lambda i : num_accu.add(i))
    # drive端通过value】拉取
    print(num_accu.value)
    print("######## accumulator #########")
    
    sc.stop()
    

53c7c789f5e2d30bc5eaedfcb2382397.png
scala

5725d1ed5422482f9fcbd8bb44b7b08a.png
python
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值