Spark——共享变量

Spark提供两种共享变量:Broadcast Variable和Accumulator。Broadcast Variable通过在每个节点仅保存一份副本,减少网络传输和内存消耗,适合优化性能。Accumulator则允许多个task累加操作,但只允许Driver读取其值,task不能读取。文章介绍了两种变量的工作原理、使用方法及实战示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、共享变量工作原理

  • Spark一个非常重要的特性就是共享变量。
  • 默认情况下,如果在一个算子的函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中。此时每个task只能操作自己的那份变量副本。如果多个task想要共享某个变量,那么这种方式是做不到的。
  • Spark为此提供了两种共享变量,一种是Broadcast Variable(广播变量),另一种是Accumulator(累加变量)。Broadcast Variable会将使用到的变量,仅仅为每个节点拷贝一份,更大的用处是优化性能,减少网络传输以及内存消耗。Accumulator则可以让多个task共同操作一份变量,主要可以进行累加操作。

二、广播变量(Broadcast Variable)

1、介绍
  • Spark提供的Broadcast Variable,是只读的。并且在每个节点上只会有一份副本,而不会为每个task都拷贝一份副本。因此其最大作用,就是减少变量到各个节点的网络传输消耗,以及在各个节点上的内存消耗。此外,spark自己内部也使用了高效的广播算法来减少网络消耗。
  • 可以通过调用SparkContext的broadcast()方法,来针对某个变量创建广播变量。然后在算子的函数内,使用到广播变量时,每个节点只会拷贝一份副本了。每个节点可以使用广播变量的value()方法获取值。记住,广播变量,是只读的。
2、实战

① 基于java

package cn.spark.study.core;

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.Function;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.broadcast.Broadcast;

import java.util.Arrays;
import java.util.List;

public class BroadcastVariable {

    public static void main(String[] args) {
        SparkConf conf = new SparkConf()
                .setMaster("local")
                .setAppName("BroadcastVariable");

        JavaSparkContext sc = new JavaSparkContext(conf);

        final int factor = 3;

        final Broadcast<Integer> broadcast = sc.broadcast(factor);


        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5);

        JavaRDD<Integer> numbers = sc.parallelize(numberList);

        JavaRDD<Integer> map = numbers.map(new Function<Integer, Integer>() {
            @Override
            public Integer call(Integer integer) throws Exception {

                final Integer value = broadcast.value();
                return integer * value;
            }
        });

        map.foreach(new VoidFunction<Integer>() {
            @Override
            public void call(Integer integer) throws Exception {
                System.out.println(integer);
            }
        });
    }
}

在这里插入图片描述
② 基于scala

package cn.spark.study.core

import org.apache.spark.broadcast.Broadcast
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object BroadcastVariable {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setMaster("local")
      .setAppName("BroadcastVariable")
    val sc = new SparkContext(conf)
    val factor = 3
    val bioadcast: Broadcast[Int] = sc.broadcast(factor)

    val num = Array(1,2,3,4,5)
    val numRDD: RDD[Int] = sc.parallelize(num)

    numRDD.map(_ * bioadcast.value).foreach(println)
  }
}

在这里插入图片描述

二、累加变量(Accumulator)

1、介绍
  • Spark提供的Accumulator,主要用于多个节点对一个变量进行共享性的操作。Accumulator只提供了累加的功能。但是确给我们提供了多个task对一个变量并行操作的功能。但是task只能对Accumulator进行累加操作,不能读取它的值。只有Driver程序可以读取Accumulator的值。
2、实践

① 基于java

package cn.spark.study.core;

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.VoidFunction;

import java.util.Arrays;
import java.util.List;

public class AccumulatorVariable {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf()
                .setMaster("local")
                .setAppName("AccumulatorVariable");
        JavaSparkContext sc = new JavaSparkContext(conf);

        // 创建Accumulator变量
        // 需要调用SparkContext的accumulator()方法
        final Accumulator<Integer> sum = sc.accumulator(100);
        final Accumulator<Integer> sum1 = sc.accumulator(10);
        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5);
        JavaRDD<Integer> numbers = sc.parallelize(numberList);

        numbers.foreach(new VoidFunction<Integer>() {
            @Override
            public void call(Integer integer) throws Exception {
                sum.add(integer);
                sum1.add(integer);
            }
        });

        sum1.setValue(10);
        System.out.println(sum.value() + ":" + sum.id() + ":" + sum1.id() + ":" + sum1.value());
    }
}

在这里插入图片描述
② 基于scala

package cn.spark.study.core

import org.apache.spark.{SparkConf, SparkContext}

object AccumulatorVariable {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setMaster("local")
      .setAppName("AccumulatorVariable")
    val sc = new SparkContext(conf)
    val sum = sc.accumulator(0)
    val num = Array(1, 2, 3, 4, 5)
    sc.parallelize(num).foreach(sum += _)
    println(sum)
  }
}

在这里插入图片描述

Spark广播变量是一种分布式只读共享变量。它通过将一个普通变量封装为广播变量,使得该变量可以在Executor端执行的代码中使用。广播变量的使用非常简单,只需要使用`broadcast`方法将一个普通变量封装为广播变量即可。例如,可以使用以下代码将一个可变的映射封装为广播变量: ``` val map = mutable.Map(("a", 4),("b", 5),("c", 6)) val bc: Broadcast[mutable.Map[String, Int]] = sc.broadcast(map) ``` 这样,在Executor端的代码中可以通过`bc.value`来获取广播变量的值,而不需要将整个变量传递到Executor端。广播变量的主要作用是可以在并行计算中共享数据,减少数据传输的开销,提高计算效率。因为广播变量在Executor端是只读的,所以不会出现数据一致性的问题。这使得广播变量非常适合在分布式计算中共享一些大型的只读数据集。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spark共享变量(广播变量、累加器)](https://blog.youkuaiyun.com/Android_xue/article/details/79780463)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [spark 累加器,广播变量.docx](https://download.youkuaiyun.com/download/weixin_41801538/12279398)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Spark学习笔记(15)——广播变量](https://blog.youkuaiyun.com/m0_56602092/article/details/119452562)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值