[笔记迁移][Spark][7]共享变量:Broadcast Variable & Accumulator

1. 概述

    默认情况下,若在一个算子函数中使用到了来自外部的某个变量,则该变量的值会被拷贝到每个Task中,此时每个Task只能操作自己获得的副本,而无法实现多个Task间的共享。
    Spark为此提供了两种共享变量,一种是Broadcast Variable(广播变量),另一种是Accumulator(累加变量):
(1)Broadcast Variable将被使用到的变量,仅为 “每个节点” 拷贝一份,减少每个Task拷贝副本的网络传输及内存消耗,优化性能。
(2)Accumulator可以让多个Task共同操作一份变量,实现“并发写”,主要进行累加。
SharedVariable

2. Broadcast Variable

   广播变量是只可读不可写的,每个节点上只会有一份副本,而不会为每个Task都拷贝一份副本。 因此,减少了变量至各个节点的网络传输消耗以及在各个节点上的内存消耗。此外,Spark在内部使用了高效的广播算法来减少网络消耗。
   通过SparkContext.broadcast(variable),来创建对应variable的广播变量,然后在算子中使用到广播变量时,每个节点只会拷贝一份副本。每个节点可以使用广播变量的value()进行取值。
(1)java版本

	/**
	 * 广播变量
	 * @author Z -Jay
	 *
	 */
	public class BroadcastVariable {
	      
	       public static void main(String[] args) {
	            SparkConf conf = new SparkConf().setAppName("BroadcastVariable" ).setMaster("local");
	            
	            JavaSparkContext sc = new JavaSparkContext(conf );
	            
	            Integer factor = 3;
	            
	             //Java中创建factor的共享广播变量,返回Broadcast<T>,每个节点拷贝一份
	             final Broadcast<Integer> broadcastFactor = sc.broadcast(factor );
	            
	            List<Integer> numList = Arrays.asList(1,2,3,4,5);
	            
	            JavaRDD<Integer> javaRDD = sc .parallelize(numList);
	            
	             //让RDD中的每个数字与外部定义的factor相乘
	            JavaRDD<Integer> resRDD = javaRDD .map(new Function<Integer, Integer>() {
	
	                   private static final long serialVersionUID = 1L;
	
	                   @Override
	                   public Integer call(Integer num ) throws Exception {
	                         // 获取该节点共享变量的值
	                        Integer factor = broadcastFactor .value();
	                         return num *factor ;
	                  }
	            });
	            
	             resRDD.foreach(new VoidFunction<Integer>() {
	                   private static final long serialVersionUID = 1L;
	
	                   @Override
	                   public void call(Integer num) throws Exception {
	                        System. out.println(num );
	                  }
	            });
	            
	             sc.close();
	      }
	}

(2)scala版本

  def main(args:Array[String]){
    val conf =new SparkConf().setAppName ("BroadcastVariable" ).setMaster ("local" )
   
    val sc = new SparkContext(conf )
   
    val factor = 3
   
    val broadcastFactor = sc. broadcast(factor)
   
    val numArray = Array(1,2,3,4,5)
   
    val srcRDD = sc.parallelize(numArray, 5)
   
    val multiRDD = srcRDD.map{ num => num*broadcastFactor.value }
   
    multiRDD.foreach{ num => println(num) }
  }

3. Accumulator

  累加变量主要用于多个Task对一个变量 “并发写”,但Task只能进行累加操作,不能读取它的值,只有Driver节点的程序可以读取Accumulator的值。
  通过SparkContext.accumulator(variable),来创建variable的广播变量。

/**
 * 累加变量
 * @author Z -Jay
 *
 */
public class AccumulatorVariable {
      
       public static void main(String[] args) {
            SparkConf conf = new SparkConf().setAppName("AccumulatorVariable" ).setMaster("local");
            
            JavaSparkContext sc = new JavaSparkContext(conf);
            
             //Java中创建共享累加变量,返回Accumulator<T>
             Accumulator<Integer> sum = sc .accumulator (0);
            
            List<Integer> numList = Arrays.asList(1,2,3,4,5);
            
            JavaRDD<Integer> javaRDD = sc .parallelize(numList);
            
             javaRDD.foreach(new VoidFunction<Integer>() {
                  
                   private static final long serialVersionUID = 1L;

                   @Override
                   public void call(Integer val) throws Exception {
                         //在算子函数内使用Accumulator.add()累加
                         sum.add(val);
                  }
            });
            
             //在Driver程序中调用Accumulator.val()获取其值
            System. out.println(sum .value ());
            
             sc.close();
      }
      
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值