Spak基础—3、共享变量

5、共享变量

广播变量主要分为广播变量和累加器

5-1、广播变量

广播变量的特点:

  1. 只读的数据,不是RDD
  2. 只能再Driver定义或修改,无法在Executor 定义或修改
  3. 在各个节点保存,不用因为任务再来回传输,直接读取本地
  4. 一个Executor有一份副本

广播变量的优点:

  1. 不需要再来回传输,因此也减少了反复的序列化和反序列化
  2. 频繁使用的变量会导致Executor的每个task都有一份副本,但是广播后同一个Executor共享一个副本,减少不必要的网络传输和GC

广播变量使用的场景:

  1. 频繁使用的变量,这样的话可以减少不必要的副本和网络传输以及大量的GC
  2. 小表连接大表时,广播小表,这样可以减少网络传输,性能更高

广播变量的Java Demo:

/*
*这里将数组放入广播变量中,使用的时候直接读取即可
*/
	    SparkConf conf = new SparkConf();
        JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
        ArrayList<String> list = new ArrayList<String>();
        list.add("张_三");
        list.add("李_四");
        list.add("王_五");
        list.add("王_五");
        loger.info("任务开始");
        loger.info(String.valueOf(list));
        JavaRDD<String> javaRDD = sc.parallelize(list);
        //共享变量
        ArrayList<String> bro_list = new ArrayList<>();
        bro_list.add("第一名");
        bro_list.add("第二名");
        bro_list.add("第三名");
        bro_list.add("第四名");
        final Broadcast<ArrayList<String>> broadcast = sc.broadcast(bro_list);

        //使用broadcast
        JavaRDD<String> broadcast_map = javaRDD.map(new Function<String, String>() {
            int i = 0;
            ArrayList<String> value = broadcast.value();

            @Override
            public String call(String s) throws Exception {
                String result = s + value.get(i);
                i += 1;
                return result;
            }
        });
        loger.info(String.valueOf(broadcast_map.collect()));

结果如下:
     [张_三第一名, 李_四第二名, 王_五第三名, 王_五第四名]
5-2、累加器

可以发生改变的共享变量,由Driver初始化并读取值,Executor进行操作修改,只要有一个Executor对其进行修改,那么全局就会改变,可以作为计数器或求和器。

累加器特点:

  1. Driver初始化或读取,Executor修改
  2. 一经修改,全局生效

累加器的适用场景:

  1. 统计计算中的某些事件的数量
  2. 求和器

累加器的Java Demo

  
	    SparkConf conf = new SparkConf();
        JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
        ArrayList<String> list = new ArrayList<String>();
        list.add("张_三");
        list.add("李_四");
        list.add("王_五");
        list.add("王_五");
        loger.info("任务开始");
        loger.info(String.valueOf(list));
        JavaRDD<String> javaRDD = sc.parallelize(list);
        SparkSession spark = SparkSession.builder().master("local[*]").getOrCreate();
        LongAccumulator longAccumulator = spark.sparkContext().longAccumulator();
        javaRDD.map(new Function<String, String>() {
            @Override
            public String call(String s) throws Exception {
                longAccumulator.add(1);
                return s+"累加";
            }
        });
        loger.info("------------------------------------");
        loger.info(String.valueOf(longAccumulator));
        loger.info("------------------------------------");
        mapRdd.count();
        loger.info(String.valueOf(longAccumulator));
        loger.info("------------------------------------");
        mapRdd.count();
        loger.info(String.valueOf(longAccumulator));
        loger.info("------------------------------------");
		
结果是:
    -------------------------
    0
    -------------------------
    4
    -------------------------
    8
//这里说明累加器也是惰性的,如果放在转换操作后面,而且每一次相同rdd触发动作操作,因为会从头获取RDD,所以累加操作就会重新操作一遍,所以是0、4、8
//单纯的action操作就不会带来问题

如果要精准的计算某个操作累加的次数,那么就在计算的transform操作后将RDD给cache下来,这样之后的各种操作都不会再执行累加器那边的算子操作,等于切断血缘,示例如下:

  
	    SparkConf conf = new SparkConf();
        JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
        ArrayList<String> list = new ArrayList<String>();
        list.add("张_三");
        list.add("李_四");
        list.add("王_五");
        list.add("王_五");
        loger.info("任务开始");
        loger.info(String.valueOf(list));
        JavaRDD<String> javaRDD = sc.parallelize(list);        
	    SparkSession spark = SparkSession.builder().master("local[*]").getOrCreate();
        LongAccumulator longAccumulator = spark.sparkContext().longAccumulator();
        JavaRDD<String> mapRdd = javaRDD.map(new Function<String, String>() {
            @Override
            public String call(String s) throws Exception {
                longAccumulator.add(1);
                return s + "累加";
            }
        });
        JavaRDD<String> cache = mapRdd.cache();
        loger.info("------------------------------------");
        loger.info(String.valueOf(longAccumulator));
        loger.info("------------------------------------");
        cache.count();
        loger.info(String.valueOf(longAccumulator));
        loger.info("------------------------------------");
        cache.count();
        loger.info(String.valueOf(longAccumulator));
        loger.info("------------------------------------");

结果
    --------------------
    0
    --------------------
    4
    --------------------
    4

//因为cache切断了和之前的血缘,无需再进行map操作获取mapRdd,所以,累加器不会操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值