Spark(Accumulator)陷阱及解决办法

Accumulator简介

Accumulator是spark提供的累加器,顾名思义,该变量只能够增加。

只有driver能获取到Accumulator的值(使用value方法),Task只能对其做增加操作(使用 +=)。你也可以在为Accumulator命名(不支持Python),这样就会在spark web ui中显示,可以帮助你了解程序运行的情况。

Accumulator使用

使用示例

举个最简单的accumulator的使用例子:

//在driver中定义

val accum = sc.accumulator(0, "Example
Accumulator")

//在task中进行累加

sc.parallelize(1 to 10).foreach(x=> accum += 1)

//在driver中输出

accum.value

//结果将返回10

res: 10

累加器的错误用法

val accum= sc.accumulator(0, "Error
Accumulator")

val data = sc.parallelize(1 to 10)

//用accumulator统计偶数出现的次数,同时偶数返回0,奇数返回1

val newData = data.map{x => {

if(x%2 == 0){

accum += 1

0

}else 1

}}

//使用action操作触发执行

newData.count

//此时accum的值为5,是我们要的结果

accum.value

//继续操作,查看刚才变动的数据,foreach也是action操作

newData.foreach(println)

//上个步骤没有进行累计器操作,可是累加器此时的结果已经是10了

//这并不是我们想要的结果

accum.value

原因分析

官方对这个问题的解释如下描述:

For accumulator updates performed inside actions
only, Spark guarantees that each task’s update to the accumulator will only be applied once, i.e.
restarted tasks will not update the value. In transformations, users should be
aware of that each task’s update may be applied more
than once if tasks or job stages are re-executed.

我们都知道,spark中的一系列transform操作会构成一串长的任务链,此时需要通过一个action操作来触发,accumulator也是一样。因此在一个action操作之前,你调用value方法查看其数值,肯定是没有任何变化的。

所以在第一次count(action操作)之后,我们发现累加器的数值变成了5,是我们要的答案。

之后又对新产生的的newData进行了一次foreach(action操作),其实这个时候又执行了一次map(transform)操作,所以累加器又增加了5。最终获得的结果变成了10。

解决办法

看了上面的分析,大家都有这种印象了,那就是使用累加器的过程中只能使用一次action的操作才能保证结果的准确性。

事实上,还是有解决方案的,只要将任务之间的依赖关系切断就可以了。什么方法有这种功能呢?你们肯定都想到了,cache,persist。调用这个方法的时候会将之前的依赖切除,后续的累加器就不会再被之前的transfrom操作影响到了。

//

val accum= sc.accumulator(0, "Error
Accumulator")

val data = sc.parallelize(1 to 10)

//代码和上方相同

val newData = data.map{x => {...}}

//使用cache缓存数据,切断依赖。

newData.cache.count

//此时accum的值为5

accum.value

newData.foreach(println)

//此时的accum依旧是5

accum.value

总结

使用Accumulator时,为了保证准确性,只使用一次action操作。如果需要使用多次则使用cache或persist操作切断依赖。

时间: 2024-10-04 06:31:34

Spark(Accumulator)陷阱及解决办法的相关文章

在IntelliJ中运行Spark Demo时遇到的问题及解决办法

这一阶段主要是在学习Scala,知乎上说推荐先学习一下Haskell再学习Scala,但我觉得不一定要曲线救国.不过在学习过程中遇到的困难的确不少,好歹Scala是公认的其特性的复杂程度是要超过C++的嘛:-) 我学习Scala的主要动机是想研究Spark,尽管Python和Java等都可以用来开发Spark应用,但是Spark本身就是一个Scala项目,而且Spark也不能算是一个成熟的产品,也许在我遇到问题的时候用Scala可以更加高效的解决问题 今天初步看了部分Spark的官方文档,在In

spark on yarn运行产生缺jar包错误及解决办法

1.本地运行出错及解决办法 当运行如下命令时: ./bin/spark-submit --class org.apache.spark.examples.mllib.JavaALS --master local[*] /opt/cloudera/parcels/CDH-5.1.2-1.cdh5.1.2.p0.3/lib/hadoop-yarn/lib/spark-examples_2.10-1.0.0-cdh5.1.2.jar /user/data/netflix_rating 10 10 /u

普通网站的SEO三大难点及解决办法

听了ZAC的剖析SEO中心技能讲座 ,因为对SEO方面的内容一笔带过,这次具体写一下.在这次讲座有一页PPT信息量十分大,其本页PPT简直囊括了SEO技能的方方面面,其间在SEO方面有三大难点,一直困扰着站长,下面就着重讲解一下.提示:本文内容是按照我本人的了解来写的,并不全包括ZAC的内容.? SEO三大难点以及解决方案 1.内部链接结构 现在没有一个大型网站能做到100%录入网页.内链的好坏决议蜘蛛的抓取.坏的内链会形成录入削减,影响流量,杰出链接结构的意图是增强内部权重活动和散布,添加收录

如何用 Android Studio 导入开源项目以及常见错误的解决办法

声明:这篇文章完全来自这篇文章,感谢大神的相助.这篇文章纯粹是为了备份. 本篇以Github上最热门的MaterialDesign库,MaterialDesignLibrary来介绍怎样使用Android Sudio导入开源项目的,如果你和我一样刚刚从Eclipse转到AS,那本篇文章非常适合你. 如果不引入任何第三方库,不做自动化分渠道打包等操作,那可以在完全不了解Gradle的情况下进行Android项目的开发.但如果要想导入Github上的热门项目,必须首先熟悉Gradle. 1. Gra

phpstudy无法访问主页,提示You don't have permission to access / on this server解决办法

1.输入localhost提示:You don't have permission to access / on this server. 新版phpStudy为了安全,取消Apache和nginx列出目录内容. phpStudy如何禁止或允许站点目录列表 请使用『其他选项菜单』-『phpStudy设置』-『允许目录列表』,打上对勾表示允许目录列表,去掉对勾表示禁止目录列表. 2.配置多域名的虚拟主机总是失败,提示You don't have permission to access / on

MySQL 警告WARN: Establishing SSL connection without server's identity verification is not recommended.解决办法

Success loading Mysql Driver!Mon Apr 04 15:43:00 CST 2016 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by d

mp4网页播放代码,有声音无图像的解决办法~

mp4网页播放代码,有声音无图像的解决办法~ 关于网页播放mp4格式的视频,找了一些插件,这里推荐一下video.js 官方网址:http://www.videojs.com/ github :https://github.com/videojs/video.js/ demo:http://www.videojs.com/downloads/video-js-4.12.5.zip 使用方法: ①引入文件:指派flash播放的swf文件 <link href="//example.com/p

Linux环境下启动MySQL数据库出现找不到mysqld.sock的解决办法!

问题: 在普通用户权限下运行:mysql -u root -p,回车之后如果会出现如下错误:ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) 此错误的意思就是没有找到mysqld.sock文件. 解决办法: 首先进入超级用户root权限  sudo -i 或者su - root 切换到默认目录 cd /var/lib/mysql  下查看

方法中的函数会掩盖this,解决办法!

要知道在javascript中this是种很神奇的东西,但是有时候也很淘气: 如下: <script> var obj = { name: 'tqt', friends: ['shangs', 'lisi'], sayHello: function() { this.friends.forEach(function(friend){ console.log(this.name + ' say hello to ' + friend); }); }, } obj.sayHello(); //sa