java的变量累加_广播变量&累加变量

1、 广播&累加器

我们传递给Spark的函数,如map(),或者filter()的判断条件函数,能够利用定义在函数之外的变量,但是集群中的每一个task都会得到变量的一个副本,并且task在对变量进行的更新不会被返回给driver。而Spark的两种共享变量:累加器(accumulator)和广播变量(broadcast variable),在广播和结果聚合这两种常见类型的通信模式上放宽了这种限制。 使用累加器可以很简便地对各个worker返回给driver的值进行聚合。

由于对于worker节点来说,累加器的值是不可访问的,所有对于worker上的task,累加器是write-only的。这使得累加器可以被更高效的实现,而不需要在每次更新时都进行通信。

Spark保证:在终止操作中对累加器的操作只执行一次,而转化操作中则可能多次执行。

累加器的操作可以多种,比如算术加法 MAX,只要这些操作符合交换律和结合律。

累加器会多次传递给Executor节点(而广播只一次)。

1. Accumulator

import java.util.ArrayList;

import java.util.List;

import org.apache.spark.Accumulator;

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaRDD;

import org.apache.spark.api.java.JavaSparkContext;

import org.apache.spark.api.java.function.PairFunction;

import org.apache.spark.broadcast.Broadcast;

import scala.Tuple2;

public class AccumulatorDemo {

public static void main(String[] xx){

SparkConf conf = new SparkConf();

conf.setMaster("local[4]");

conf.setAppName("WordCounter");

conf.set("spark.default.parallelism", "4");

conf.set("spark.testing.memory", "2147480000");

JavaSparkContext ctx = new JavaSparkContext(conf);

Person[] persons = new Person[10000];

Broadcast persons_br = ctx.broadcast(persons);

Accumulator count = ctx.accumulator(0);

List data1 = new ArrayList();

data1.add("Cake");

data1.add("Bread");

data1.add("");

data1.add("Cheese");

data1.add("Milk");

data1.add("Toast");

data1.add("Bread");

data1.add("");

data1.add("Egg");

data1.add("");

JavaRDD rdd1 = ctx.parallelize(data1, 2);

System.out.println(rdd1.glom().collect());

rdd1.mapToPair(new PairFunction() {

@Override

public Tuple2 call(String s) throws Exception {

long id = Thread.currentThread().getId();

System.out.println("s:" + s + " in thread:" + id);

if(s.equals("")){

count.add(1);

}

return new Tuple2(s, 1);

}

}).collect();

System.out.println(count.value());

rdd1.mapToPair(new PairFunction() {

@Override

public Tuple2 call(String s) throws Exception {

long id = Thread.currentThread().getId();

System.out.println("s:" + s + " in thread:" + id);

if(s.equals("")){

count.add(1);

// System.out.println("c:"+count.value());

}

System.out.println(persons_br.value().length);

return new Tuple2(s, 1);

}

}).collect();

System.out.println(count.value());

ctx.stop();

}

}

class Person{}

2.BroadCast

import java.util.Arrays;

import java.util.List;

import org.apache.spark.Accumulator;

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaPairRDD;

import org.apache.spark.api.java.function.Function;

import org.apache.spark.api.java.function.Function2;

import org.apache.spark.api.java.function.PairFunction;

import org.apache.spark.broadcast.Broadcast;

import org.apache.spark.streaming.Durations;

import org.apache.spark.streaming.Time;

import org.apache.spark.streaming.api.java.JavaPairDStream;

import org.apache.spark.streaming.api.java.JavaReceiverInputDStream;

import org.apache.spark.streaming.api.java.JavaStreamingContext;

import scala.Tuple2;

/**

* 实例:利用广播进行黑名单过滤! 检查新的数据 根据是否在广播变量-黑名单内,从而实现过滤数据。

*/

public class BroadCastDemo {

/**

* 创建一个List的广播变量

*

*/

private static volatile Broadcast> broadcastList = null;

/**

* 计数器!

*/

private static volatile Accumulator accumulator = null;

public static void main(String[] args) {

SparkConf conf = new SparkConf().setMaster("local[2]").setAppName("WordCountOnlineBroadcast");

conf.set("spark.testing.memory", "2147480000");

JavaStreamingContext jsc = new JavaStreamingContext(conf, Durations.seconds(5));

/**

* 注意:分发广播需要一个action操作触发。 注意:广播的是Arrays的asList

* 而非对象的引用。广播Array数组的对象引用会出错。 使用broadcast广播黑名单到每个Executor中!

*/

broadcastList = jsc.sparkContext().broadcast(Arrays.asList("Hadoop", "Mahout", "Hive"));

/**

* 累加器作为全局计数器!用于统计在线过滤了多少个黑名单! 在这里实例化。

*/

accumulator = jsc.sparkContext().accumulator(0, "OnlineBlackListCounter");

JavaReceiverInputDStream lines = jsc.socketTextStream("Master", 9999);

/**

* 这里省去flatmap因为名单是一个个的!

*/

JavaPairDStream pairs = lines.mapToPair(new PairFunction() {

@Override

public Tuple2 call(String word) {

return new Tuple2(word, 1);

}

});

JavaPairDStream wordsCount = pairs.reduceByKey(new Function2() {

@Override

public Integer call(Integer v1, Integer v2) {

return v1 + v2;

}

});

/**

* Funtion里面 前几个参数是 入参。 后面的出参。 体现在call方法里面!

*

*/

//wordsCount.foreach(new Function2,Time,boolean>() {

//@Override

//public boolean call(JavaPairRDD rdd, Time time) throws Exception {

//rdd.filter(new Function, Boolean>() {

//@Override

//public Boolean call(Tuple2 wordPair) throws Exception {

//if (broadcastList.value().contains(wordPair._1)) {

///**

// * accumulator不仅仅用来计数。 可以同时写进数据库或者缓存中。

// */

//accumulator.add(wordPair._2);

//return false;

//} else {

//return true;

//}

//};

///**

// * 广播和计数器的执行,需要进行一个action操作!

// */

//}).collect();

//System.out.println("广播器里面的值" + broadcastList.value());

//System.out.println("计时器里面的值" + accumulator.value());

//return null;

//}

//});

jsc.start();

try {

jsc.awaitTermination();

} catch (InterruptedException e) {

// TODO 自动生成的 catch 块

e.printStackTrace();

}

jsc.close();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值