一、简介

在Spark中,提供了两种类型的共享变量:累加器(accumulator)与广播变量(broadcast variable):

  • 累加器:用来对信息进行聚合,主要用于累计计数等场景;
  • 广播变量:主要用于在节点间高效分发大对象。

二、累加器

这里先看一个具体的场景,对于正常的累计求和,如果在集群模式中使用下面的代码进行计算,会发现执行结果并非预期:

var counter = 0
val data = Array(1, 2, 3, 4, 5)
sc.parallelize(data).foreach(x => counter += x)
 println(counter)

counter最后的结果是0,导致这个问题的主要原因是闭包。

2.1 理解闭包

1. Scala中闭包的概念

这里先介绍一下Scala中关于闭包的概念:

var more = 10
val addMore = (x: Int) => x + more

如上函数addMore中有两个变量x和more:

  • x : 是一个绑定变量(bound variable),因为其是该函数的入参,在函数的上下文中有明确的定义;
  • more : 是一个自由变量(free variable),因为函数字面量本生并没有给more赋予任何含义。

按照定义:在创建函数时,如果需要捕获自由变量,那么包含指向被捕获变量的引用的函数就被称为闭包函数。

2. Spark中的闭包

在实际计算时,Spark会将对RDD操作分解为Task,Task运行在Worker Node上。在执行之前,Spark会对任务进行闭包,如果闭包内涉及到自由变量,则程序会进行拷贝,并将副本变量放在闭包中,之后闭包被序列化并发送给每个执行者。因此,当在foreach函数中引用counter时,它将不再是Driver节点上的counter,而是闭包中的副本counter,默认情况下,副本counter更新后的值不会回传到Driver,所以counter的最终值仍然为零。

需要注意的是:在Local模式下,有可能执行foreach的Worker Node与Diver处在相同的JVM,并引用相同的原始counter,这时候更新可能是正确的,但是在集群模式下一定不正确。所以在遇到此类问题时应优先使用累加器。

累加器的原理实际上很简单:就是将每个副本变量的最终值传回Driver,由Driver聚合后得到最终值,并更新原始变量。

2.2 使用累加器

SparkContext中定义了所有创建累加器的方法,需要注意的是:被中横线划掉的累加器方法在Spark 2.0.0之后被标识为废弃。

使用示例和执行结果分别如下:

val data = Array(1, 2, 3, 4, 5)
// 定义累加器
val accum = sc.longAccumulator("My Accumulator")
sc.parallelize(data).foreach(x => accum.add(x))
// 获取累加器的值
accum.value

三、广播变量

在上面介绍中闭包的过程中我们说道每个Task任务的闭包都会持有自由变量的副本,如果变量很大且Task任务很多的情况下,这必然会对网络IO造成压力,为了解决这个情况,Spark提供了广播变量。

广播变量的做法很简单:就是不把副本变量分发到每个Task中,而是将其分发到每个Executor,Executor中的所有Task共享一个副本变量。

// 把一个数组定义为一个广播变量
val broadcastVar = sc.broadcast(Array(1, 2, 3, 4, 5))
// 之后用到该数组时应优先使用广播变量,而不是原值
sc.parallelize(broadcastVar.value).map(_ * 10).collect()

参考资料

RDD Programming Guide

更多大数据系列文章可以参见个人 GitHub 开源项目: 程序员大数据入门指南

Spark学习之路(六)—— 累加器与广播变量的更多相关文章

  1. Spark学习之编程进阶——累加器与广播(5)

    Spark学习之编程进阶--累加器与广播(5) 1. Spark中两种类型的共享变量:累加器(accumulator)与广播变量(broadcast variable).累加器对信息进行聚合,而广播变 ...

  2. [转]Spark学习之路 (三)Spark之RDD

    Spark学习之路 (三)Spark之RDD   https://www.cnblogs.com/qingyunzong/p/8899715.html 目录 一.RDD的概述 1.1 什么是RDD? ...

  3. Spark学习之路 (四)Spark的广播变量和累加器

    一.概述 在spark程序中,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的是这个函数所用变量的一个独立副本.这些变量会被复制到每台机器上 ...

  4. Spark学习之路 (四)Spark的广播变量和累加器[转]

    概述 在spark程序中,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的是这个函数所用变量的一个独立副本.这些变量会被复制到每台机器上,并 ...

  5. Spark 系列(六)—— 累加器与广播变量

    一.简介 在 Spark 中,提供了两种类型的共享变量:累加器 (accumulator) 与广播变量 (broadcast variable): 累加器:用来对信息进行聚合,主要用于累计计数等场景: ...

  6. Spark——DataFrames,RDD,DataSets、广播变量与累加器

    Spark--DataFrames,RDD,DataSets 一.弹性数据集(RDD) 创建RDD 1.1RDD的宽依赖和窄依赖 二.DataFrames 三.DataSets 四.什么时候使用Dat ...

  7. Spark学习之路 (九)SparkCore的调优之数据倾斜调优

    摘抄自:https://tech.meituan.com/spark-tuning-pro.html 数据倾斜调优 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Sp ...

  8. Spark学习之路 (八)SparkCore的调优之开发调优

    摘抄自:https://tech.meituan.com/spark-tuning-basic.html 前言 在大数据计算领域,Spark已经成为了越来越流行.越来越受欢迎的计算平台之一.Spark ...

  9. Spark入门3(累加器和广播变量)

    一.概要 通常情况下,当向Spark操作传递一个函数时,它会在一个远程集群节点上执行,它会使用函数中所有变量的副本.这些变量被复制到所有的机器上,远程机器上并没有被更新的变量会向驱动程序回传.在任务之 ...

随机推荐

  1. Leetcode 617 Merge Two Binary Trees 二叉树

    题意: 给定两棵树,将两棵树合并成一颗树 输入 Tree 1 Tree 2 1 2 / \ / \ 3 2 1 3 / \ \ 5 4 7 输出 合并的树 3 / \ 4 5 / \ \ 5 4 7 ...

  2. Information centric network (icn) node based on switch and network process using the node

    The present invention relates to an apparatus for supporting information centric networking. An info ...

  3. 微信公众平台中临时二维码的scene_id为32位非0整型

    原文:微信公众平台中临时二维码的scene_id为32位非0整型                                        微信公众平台中临时二维码的scene_id为32位非0整 ...

  4. Delphi读取文件属性

    Read File Detailed Properties https://www.board4all.biz/threads/read-file-detailed-properties.655787 ...

  5. 简明Python3教程 6.基础

    你肯定不满足于只打印"Hello World"吧? 你想要的更多 - 你希望得到一些输入,操纵它后再从中得到某些东西.我们可以使用python中的常量和变量实现这些功能. 字面常量 ...

  6. Select2使用方法汇总

    引用: <script src="~/Content/plugins/select2/select2.min.js"></script> 1.简单使用 $. ...

  7. Xamarin 设置可接受的版本

    一共分三个版本,编译版本.最小版本.目标版本(最适应) 一般编译使用最新的版本,目标版本选择最主流的 参考资料 https://docs.microsoft.com/en-us/xamarin/and ...

  8. MVC 用基架创建Controller,通过数据库初始化器生成并播种数据库

    1 创建MVC应用程序 2 在Model里面创建实体类 using System; using System.Collections.Generic; using System.Linq; using ...

  9. UBUTUN 通过蓝牙连接Hoary和诺基亚手机

    通过蓝牙连接Hoary和诺基亚手机 这个how to已经用Hoary.诺基亚6630和一个道尔芯片(Dongle)蓝牙(Usb蓝牙)测试过了.通过这个How to,你可以:-通过蓝牙,从你的电脑发送文 ...

  10. SqlServer 更改复制代理配置文件参数及两种冲突策略设置

    原文:SqlServer 更改复制代理配置文件参数及两种冲突策略设置 由于经常需要同步测试并更改代理配置文件属性,所以总结成脚本,方便测试. 可更新订阅的冲突策略有两种情况:一是在发布中冲突,即订阅数 ...