spark 使用的架构是无共享的,数据分布在不同节点,每个节点有独立的 CPU、内存,不存在全局的内存使得变量能够共享,驱动程序和任务之间通过消息共享数据

举例来说,如果一个 RDD 操作使用了驱动程序中的变量,spark 会将这个变量的副本和 task 一起发送给 executor 中的执行者,对该变量的更新只存在于 task 的内部,并不会回传给驱动程序;

如果这个任务分为多个阶段,每个阶段开始时,驱动程序会把 变量 发送给 worker;

在实际场景中,驱动程序在 task 间共享一个巨大(如 100M)的查找表,并且该 task 有多个(如 10个)阶段,spark 会在每个阶段开始时,给每个 task 发送一份数据,那就是 1000M 的传输和存储

显然浪费资源且效率低下;

除此之外,有时我们需要不同节点的多个任务更新一个全局变量,然而这个变量并不回传给驱动程序,又如何同步更新呢?

共享变量

spark 提供了共享变量的概率满足上述需求

spark 提供了两种共享变量:广播变量 和 累加器

上图描述了共享变量的工作原理

共享变量的作用在于 减少网络传输,减少内存消耗;

其实是一种 spark 编程的优化方法

spark 三大数据结构

RDD:分布式数据集

广播变量:分布式只读共享变量

累加器:分布式只写共享变量

广播变量

spark 只会给 worker 发送一次广播变量(序列化的),并且将它反序列化后存储在 executor 的内存中;

如果任务分为多个阶段,且每个阶段使用相同的变量,那么广播变量就无需每个阶段都传输数据,spark 会将传输过来的数据序列化后存储在 executor 的内存中,在任务开始前反序列化广播变量即可;

使用场景

1. 需要共享一个很大的数据集

2. 任务分为多个阶段,每个阶段使用相同的数据

使用方法

SparkContext.broadcast 方法用于创建一个广播变量;

broadcast 输入一个普通变量,返回一个 Broadcast 实例;

调用 Broadcast 实例的 value 属性可以获取变量值;

实例分析

import time
from pyspark import SparkContext
factor1 = ['sssssssssssssssssss']*100000 # 待广播的变量
factor2 = range(100000) if __name__ == '__main__':
time.clock()
sc = SparkContext() listRdd = sc.parallelize(factor2) ### 正确利用广播变量 # 测试:1.40s
brodacastvalue = sc.broadcast(factor1)
out = listRdd.map(lambda s: brodacastvalue.value[s-1]).collect() ### 不正确利用广播变量 # 测试:1.59s
brodacastvalue = sc.broadcast(factor1).value
out = listRdd.map(lambda s: brodacastvalue[s-1]).collect() # 这里注意了,并没有调用 广播变量,而是调用了它的 value,相当于直接调用了原来的数据 ### 不利用广播变量 # 测试:1.59s
out = listRdd.map(lambda s: factor1[s-1]).collect() print out
print(time.clock())

可以看到广播变量优化了效率,特别是替代 join 操作

累加器

累加器使得多个任务能够操作同一个全局变量, 并且能够回传给驱动程序;

它常用于计数、求和和聚合操作;

spark 支持数值型的累加,也支持自定义类型的累加;

使用方法

SparkContext.accumulator 创建一个累加器变量;

它接受两个参数:累加器的初值,累加器的名字,在 spark UI 中可看到,第二个参数可选

在 task 中只能使用累加器变量的 add 属性或者 += 来更新该变量;

在 驱动程序 中才能调用累加器变量的 value 属性,在 task 中不可以;

实例

from pyspark import SparkContext

sc = SparkContext(appName='leijiaqi')
accum = sc.accumulator(10) # 初值,名字
# sc.parallelize([1, 2, 3, 4]).foreach(lambda x : accum.add(x)) # 调用 add 属性更新变量 def myadd(x):
global accum
accum+=x
return accum
sc.parallelize([1, 2, 3, 4]).foreach(myadd) # 使用 += 方法更新变量
print(accum.value) # 20 = 10+1+2+3+4 # sc.parallelize([1, 2, 3, 4]).foreach(lambda x : accum.value) # 在 task 中调用 value 报错:Exception: Accumulator.value cannot be accessed inside tasks

总结

累加器和广播变量使用非常复杂,本文仅介绍基本用法,二者结合使用可以满足很多复杂场景

参考资料:

https://blog.csdn.net/chongxin1/article/details/78048134

https://www.jianshu.com/p/687db128ff2f  python 版

spark教程(14)-共享变量的更多相关文章

  1. Spark教程——(11)Spark程序local模式执行、cluster模式执行以及Oozie/Hue执行的设置方式

    本地执行Spark SQL程序: package com.fc //import common.util.{phoenixConnectMode, timeUtil} import org.apach ...

  2. [SQL基础教程]1-4 SQL 表的创建

    [SQL基础教程]1-4 SQL 表的创建 创建数据库 语法 CREATE DATABASE <数据库名称> // example CREATE DATABASE shop; 创建表 语法 ...

  3. spark教程

    某大神总结的spark教程, 地址 http://litaotao.github.io/introduction-to-spark?s=inner

  4. [译]Vulkan教程(14)图形管道基础之固定功能

    [译]Vulkan教程(14)图形管道基础之固定功能 Fixed functions 固定功能 The older graphics APIs provided default state for m ...

  5. [转帖]Linux教程(14)- Linux中的查找和替换

    Linux教程(14)- Linux中的查找和替换 2018-08-22 07:03:58 钱婷婷 阅读数 46更多 分类专栏: Linux教程与操作 Linux教程与使用   版权声明:本文为博主原 ...

  6. Directx11教程(14) D3D11管线(3)

    原文:Directx11教程(14) D3D11管线(3)       现在我们开始学习一些CP(command processor)的知识.参考资料: http://fgiesen.wordpres ...

  7. 深度学习与CV教程(14) | 图像分割 (FCN,SegNet,U-Net,PSPNet,DeepLab,RefineNet)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  8. spark教程(八)-SparkSession

    spark 有三大引擎,spark core.sparkSQL.sparkStreaming, spark core 的关键抽象是 SparkContext.RDD: SparkSQL 的关键抽象是 ...

  9. spark教程(九)-操作数据库

    数据库也是 spark 数据源创建 df 的一种方式,因为比较重要,所以单独算一节. 本文以 postgres 为例 安装 JDBC 首先需要 安装 postgres 的客户端驱动,即 JDBC 驱动 ...

随机推荐

  1. log4j 多进程配置要注意的

    多进程写日志文件 方法一: 解决log4j公用配置文件,多进程同时写同一个log文件,因存在操作系统pv操作问题, 导致部分日志丢失.解决方案是不同的进程写不同的log文件 测试于:Log4j 1.2 ...

  2. 05.用两个栈实现队列 Java

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路 进栈: 直接进stack1 出栈: 若stack2不为空,则出栈. 否则,当stack1不为空时, ...

  3. Python 读文件:IOError: [Errno 0] Error

    Windows系统下,这种情况发生在读取文件,再写入过程中出现. 原因是读完文件后python不知道当前文件位置在哪里. 方法一是:在关闭文件前只做读或者写一种操作. 方法二是:在写入文件前使用fil ...

  4. BitmapRegionDecoder

    Android加载大图——BitmapRegionDecoder(转)   BitmapRegionDecoder,从API10就引入了.如下图:   NPONRY0T35GE$13{254X8Z1. ...

  5. VLOOKUP的了解(1)

    上周在整理资料的时候,需要将一个表中的部分东西,弄到另外一张表中.我就傻不愣登的直接粘贴.复制.没有发现VLOOKUP呀! VLOOKUP是一个查找函数,给定一个查找的目标,它就能从指定的查找区域中查 ...

  6. wpf webbrowser取消js报错

    private void WebBrowser_Navigated(object sender, NavigationEventArgs e) { SuppressScriptErrors((WebB ...

  7. 安卓之Android.mk编写

    题记:编译环境可以参考https://www.cnblogs.com/ywjfx/p/9960817.html 不管是写C还是java,我想所有的程序员都经历过HelloWorld程序的编写,现在让我 ...

  8. qt liunx 安装命令

    qt SDK : apt-get install qt-sdkqt 安装 : apt-get install qtcreator文档安装 : cmake kdelibs5-data subversio ...

  9. 阶段3 3.SpringMVC·_03.SpringMVC常用注解_2 RequestBody注解

    拿整个请求体的数据

  10. 阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_3 配置解决中文乱码的过滤器

    输入中文 中文后台接收到 全部乱码 springMvc提供了过滤器 配置过滤器 characterEncodingFilter是首字母小写当做起的名称.当然这里也可以任意起名字.为了对应所以修改类名首 ...