Spark2.10中使用累加器、注意点以及实现自定义累加器

Spark自定义累加器Accumulator 在Spark中,除了系统提供的累加器(例如和)之外,我们还可以创建自定义累加器。自定义累加器允许我们以分布式和高效的方式累加复杂类型的数据。定义累加器的类型定义累加器将累加的数据类型。这可以是任何类型,例如整数、浮点数、集合等。继承 AccumulatorV2创建一个新类,继承自,并为其指定输入类型(IN)和输出类型(OUT)。实现必须的方法抽象类定义了一组需要被子类实现的方法。sum = 0count = 0count += 1newAccaverage在这个例子中, 阅读详情

累加器(accumulator)是Spark中提供的一种分布式的变量机制,其原理类似于mapreduce,即分布式的改变,然后聚合这些改变。累加器的一个常见用途是在调试时对作业执行过程中的事件进行计数。

累加器简单使用

Spark内置的提供了Long和Double类型的累加器。下面是一个简单的使用示例,在这个例子中我们在过滤掉RDD中奇数的同时进行计数,最后计算剩下整数的和。

[java]  view plain  copy
  1. val sparkConf = new SparkConf().setAppName("Test").setMaster("local[2]")  
  2. val sc = new SparkContext(sparkConf)  
  3. val accum = sc.longAccumulator("longAccum") //统计奇数的个数  
  4. val sum = sc.parallelize(Array(1,2,3,4,5,6,7,8,9),2).filter(n=>{  
  5.   if(n%2!=0) accum.add(1L)   
  6.   n%2==0  
  7. }).reduce(_+_)  
  8.   
  9. println("sum: "+sum)  
  10. println("accum: "+accum.value)  
  11.   
  12. sc.stop()  

结果为:

sum: 20
accum: 5

这是结果正常的情况,但是在使用累加器的过程中如果对于spark的执行过程理解的不够深入就会遇到两类典型的错误:少加(或者没加)、多加。

少加的情况:

对于如下代码:

[java]  view plain  copy
  1. val accum = sc.longAccumulator("longAccum")  
  2. val numberRDD = sc.parallelize(Array(1,2,3,4,5,6,7,8,9),2).map(n=>{  
  3.   accum.add(1L)  
  4.   n+1  
  5. })  
  6. println("accum: "+accum.value)  


执行完毕,打印的值是多少呢?答案是0,因为累加器不会改变spark的lazy的计算模型,即在打印的时候像map这样的transformation还没有真正的执行,从而累加器的值也就不会更新。

多加的情况:

对于如下代码:

[java]  view plain  copy
  1. val accum = sc.longAccumulator("longAccum")  
  2. val numberRDD = sc.parallelize(Array(1,2,3,4,5,6,7,8,9),2).map(n=>{  
  3.   accum.add(1L)  
  4.   n+1  
  5. })  
  6. numberRDD.count  
  7. println("accum1:"+accum.value)  
  8. numberRDD.reduce(_+_)  
  9. println("accum2: "+accum.value)  

结果我们得到了:

accum1:9

accum2: 18

我们虽然只在map里进行了累加器加1的操作,但是两次得到的累加器的值却不一样,这是由于count和reduce都是action类型的操作,触发了两次作业的提交,所以map算子实际上被执行了了两次,在reduce操作提交作业后累加器又完成了一轮计数,所以最终累加器的值为18。究其原因是因为count虽然促使numberRDD被计出来,但是由于没有对其进行缓存,所以下次再次需要使用numberRDD这个数据集是,还需要从并行化数据集的部分开始执行计算。解释到这里,这个问题的解决方法也就很清楚了,就是在count之前调用numberRDD的cache方法(或persist),这样在count后数据集就会被缓存下来,reduce操作就会读取缓存的数据集而无需从头开始计算了。改成如下代码即可:

[java]  view plain  copy
  1. val accum = sc.longAccumulator("longAccum")  
  2. val numberRDD = sc.parallelize(Array(1,2,3,4,5,6,7,8,9),2).map(n=>{  
  3.   accum.add(1L)  
  4.   n+1  
  5. })  
  6. numberRDD.cache().count  
  7. println("accum1:"+accum.value)  
  8. numberRDD.reduce(_+_)  
  9. println("accum2: "+accum.value)  

这次两次打印的值就会保持一致了。

自定义累加器

自定义累加器类型的功能在1.X版本中就已经提供了,但是使用起来比较麻烦,在2.0版本后,累加器的易用性有了较大的改进,而且官方还提供了一个新的抽象类:AccumulatorV2来提供更加友好的自定义类型累加器的实现方式。官方同时给出了一个实现的示例:CollectionAccumulator类,这个类允许以集合的形式收集spark应用执行过程中的一些信息。例如,我们可以用这个类收集Spark处理数据时的一些细节,当然,由于累加器的值最终要汇聚到driver端,为了避免 driver端的outofmemory问题,需要对收集的信息的规模要加以控制,不宜过大。
实现自定义类型累加器需要继承AccumulatorV2并至少覆写下例中出现的方法,下面这个累加器可以用于在程序运行过程中收集一些文本类信息,最终以Set[String]的形式返回。
[java]  view plain  copy
  1. import java.util  
  2.   
  3. import org.apache.spark.util.AccumulatorV2  
  4.   
  5. class LogAccumulator extends AccumulatorV2[String, java.util.Set[String]] {  
  6.   private val _logArray: java.util.Set[String] = new java.util.HashSet[String]()  
  7.   
  8.   override def isZero: Boolean = {  
  9.     _logArray.isEmpty  
  10.   }  
  11.   
  12.   override def reset(): Unit = {  
  13.     _logArray.clear()  
  14.   }  
  15.   
  16.   override def add(v: String): Unit = {  
  17.     _logArray.add(v)  
  18.   }  
  19.   
  20.   override def merge(other: AccumulatorV2[String, java.util.Set[String]]): Unit = {  
  21.     other match {  
  22.       case o: LogAccumulator => _logArray.addAll(o.value)  
  23.     }  
  24.   
  25.   }  
  26.   
  27.   override def value: java.util.Set[String] = {  
  28.     java.util.Collections.unmodifiableSet(_logArray)  
  29.   }  
  30.   
  31.   override def copy(): AccumulatorV2[String, util.Set[String]] = {  
  32.     val newAcc = new LogAccumulator()  
  33.     _logArray.synchronized{  
  34.       newAcc._logArray.addAll(_logArray)  
  35.     }  
  36.     newAcc  
  37.   }  
  38. }  

测试类:

[java]  view plain  copy
  1. import scala.collection.JavaConversions._  
  2.   
  3. import org.apache.spark.{SparkConf, SparkContext}  
  4.   
  5. object Main {  
  6.   def main(args: Array[String]): Unit = {  
  7.     val sparkConf = new SparkConf().setAppName("Test").setMaster("local[2]")  
  8.     val sc = new SparkContext(sparkConf)  
  9.     val accum = new LogAccumulator  
  10.     sc.register(accum, "logAccum")  
  11.     val sum = sc.parallelize(Array("1", "2a", "3", "4b", "5", "6", "7cd", "8", "9"), 2).filter(line => {  
  12.       val pattern = """^-?(\d+)"""  
  13.       val flag = line.matches(pattern)  
  14.       if (!flag) {  
  15.         accum.add(line)  
  16.       }  
  17.       flag  
  18.     }).map(_.toInt).reduce(_ + _)  
  19.   
  20.     println("sum: " + sum)  
  21.     for (v <- accum.value) print(v + " ")  
  22.     println()  
  23.     sc.stop()  
  24.   }  
  25. }  

本例中利用自定义的收集器收集过滤操作中被过滤掉的元素,当然这部分的元素的数据量不能太大。运行结果如下:
sum; 32
7cd 4b 2a 

转自 http://blog.youkuaiyun.com/u013468917/article/details/70617085
Spark自定义累加器的使用实例详解 主要介绍了Spark累加器的相关内容,首先介绍了累加器的简单使用,然后向大家分享了自定义累加器的实例代码,需要的朋友可以参考下。 立即下载

相关推荐

多目标优化NSGA-II(快速精英非支配排序遗传算法)及python实现

文章目录前言一、什么是NSGA-II?二、学习NSGA-II1.快速非支配排序算法2.密度估计3.拥挤比较算子4.主循环5.代码6.总结 前言 NSGA-II适用于复杂的多目标优化问题,是K-Deb教授在2000年在一篇paper《MOEAs — A fast and elitist multi-objective genetic algorithm: nsga2》提出。 Keywords: optimization; multi-objective evolutionary algorithm; no

ricky_blog 9744

Spark开发问题解决(二):累加器的错误使用——错误的值或空值

在spark开发中,我们有时需要在多个executor端对某些数据进行累加,这时候我们首先就会想到使用自定义累加器来实现。下面记录一下在使用自定义累加器中需要注意的点。 1、累加器值未累加 我们都知道,spark中的rdd是惰性计算的,在没有遇到action算子之前是并没有真正开始计算的,也就是说累加器没有真正的进行累加。所以遇到这种情况的朋友,先检查一下是 否没有进行action计算。 2、累加器值进行多次累加 通常情况下,我们在使用spark时会对一个RDD进行多次计算。比如说我们根据源数据创建了一.

有所谓的博客 754

论文阅读------Exposure Fusion: A Simple and Practical Alternative to High Dynamic Range Photography

Mertens T, Kautz J, Van Reeth F. Exposure fusion: A simple and practical alternative to high dynamic range photography[C]//Computer graphics forum. Oxford, UK: Blackwell Publishing Ltd, 2009, 28(1): 161-171. 摘要 本文提出了一种将包围曝光的序列融合到高质量图像中的技术,而无需先转换为高动态范围(HD.

qq_25283239的博客 3396

自定义Spark累加器

继续跟踪LongAccumulator这个类 可以看到,累加器底层其实是继承了AccumulatorV2这个方法,但是里面有两个类型参数,是什么东西呢?继续跟踪 最终是这个类型,也就是说,上面的两个参数也就是一个是输入,一个是输出 所以根据上面的源码可以知道,如果我们需要自定义自己的累加器的,只需要继承AccumulatorV2[IN, OUT] 这个类,然后重写其余的方法,自定义我们的逻辑即可 当创建完累加器之后,在使用的时候,spark是不知道我们自定义的累加器的,所有此

阿拉修 1231

CST微波工作室端口设置保姆级教程:从波导端口到离散端口,手把手教你搞定S参数仿真

本文提供CST微波工作室端口设置的详细教程,涵盖波导端口和离散端口的选择与配置,助力工程师精准完成S参数仿真。通过微带线滤波器案例,详解端口尺寸、阻抗设置及常见问题排查,提升仿真效率与准确性。

weixin_42570296的博客 361

【MUJOCO控制篇-2】控制一个简单的机械臂

本篇博客将逐步分析和解释如何通过Python代码使用MuJoCo库来控制一个机械臂模型。我们将从加载模型开始,逐步深入到PID控制器的实现,最后讨论如何实现轨迹跟踪功能。上期内容为如何建模一个简单的机械臂模型,本篇文章将基于上篇内容进行深入探讨如何实现一个简单的控制。

echo_Fangyb的博客 6747

spark 累加器

spark 累加器

qq_43192537的博客 3020

大语言模型无代码构建知识图谱概述

由示例可以看出,大语言模型的泛化能力能够非常精准的抽取文本中的实体、关系等知识信息。其能够大大提升知识提取的效率与准确性。HuggingFists低代码平台的出现进一步促进了知识图谱构建的效率。它大幅降低了知识图谱构建人员的技术要求,使得从事该工作的人员有了更大的选择范围。不断下降的构建成本,意味着可以有更多的客户享受到知识图谱带来的业务价值。

colorknight的专栏 1817

Spark:2.10中使用累加器、注意点以及实现自定义累加器Accumulator

Spark累加器剖析(1) —— 介绍 &amp; 重点类 &amp; 源码解析:https://blog.csdn.net/lemonZhaoTao/article/details/81256413 Spark累加器剖析(2) —— 累加器执行的过程:https://blog.csdn.net/lemonZhaoTao/article/details/81273243 Spark累加器剖析(...

不花的花和尚的博客 5273

AD9176 双通道高速DAC调试记录

AD9176是一款高性能双通道16位数模转换器,支持高达12.6GSPS采样率,专为多频段无线应用设计。该器件集成8通道15.4Gbps JESD204B接口,支持复数/实数数据输入,每通道最大输入速率达3.08GSPS。关键特性包括:48位高精度NCO、灵活的插值滤波器(最高12倍)、优异的动态性能(SFDR达-83dBc@1.84GHz)以及多芯片同步功能。硬件调试需重点关注时钟配置(建议250M基准时钟)、JESD参数匹配及交流耦合设计。测试指标要求SFDR>55dBc@312MHz,实测值可达65d

universaldata的博客 1489

《SAP FICO系统配置从入门到精通共40篇》030、集成配置:FI与生产计划(PP)的自动科目确定

FI和PP的自动科目确定,本质上是把生产业务翻译成会计语言。翻译规则就藏在那些配置表里。配的时候多想一步:这个业务动作,在财务眼里是什么?是材料消耗?是产出入库?还是工费分摊?想清楚这个,再看配置界面,那些代码就不是天书了。最好的测试方式,是月底关账前,让生产部门跑一遍所有类型的生产订单。配置对不对,业务最知道。

985大学毕业,前某大厂员工,啥都会点的程序员! 574

spark中使用Accumulator累加器使用和注意事项

Accumulator简介 Accumulator是spark提供的累加器,累加器的一个常用用途是在调试时对作业执行过程中的事件进行计数,但是只要driver能获取Accumulator的值(使用value方法), Task只能对其做增加操作(使用+=),也可以在为Accumulator命名(不支持Python),这样就会在spark web ui中显示, 可以帮助了解程序运行的情况。 数值累...

Ran_记忆犹新的博客 5328

〖Python WEB 自动化测试实战篇⑤〗- selenium 元素定位详解 - (八大元素定位方式)

测试对象的定位和操作是我们利用 selenium 编写自动化脚本和 webdriver 的核心内容,其中 "操作" 这一部分又是建立在 "selenium" 元素定位的基础之上的。所以对元素对象的定位就显得越发的重要,接下来我们就学习一下常用的元素定位方法有哪些。......

易编橙 · 终身成长社群,相遇已是上上签! 4万+

Spark之累加器

Spark之累加器 累加器:分布式共享只写变量。(Executor和Executor之间不能读数据) 累加器用来把Executor端变量信息聚合到Driver端。在Driver程序中定义的变量,在Executor端的每个task都会得到这个变量的一份新的副本,每个task更新这些副本的值后,传回Driver端进行merge。 1. 系统累加器 1)累加器使用 (1)累加器定义(SparkContext.accumulator(initialValue)方法) val sum: LongAccumul

weixin_42796403的博客 598

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

spark 累加器和自定义累加器 (官网介绍)

本文内容来自官网 spark自定义累加器 的api http://spark.apache.org/docs/2.1.1/api/scala/index.html#org.apache.spark.util.AccumulatorV2 累加器描述 http://spark.apache.org/docs/2.1.1/programming-guide.html#accumulators ...

weiha666的博客 640

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Spark共享变量之广播变量和自定义累加器的介绍及使用

Shared Variables(共享变量) 在 Spark 程序中,当一个传递给 Spark 操作 (例如 map 和 reduce) 的函数在远程节点上面运行时,Spark 实际上操作的是这个函数所用变量的一个独立副本。这些在Driver端声明的变量会被复制到每个Executor进程所在的执行机器上,并且这些变量在远程机器上的所有更新都不会传递回驱动程序。通常跨任务的读写变量是低效的,但是,...

程序猿丶HLK 1302

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

大数据开发之Spark(累加器、广播变量、Top10热门品类实战)

累加器:分布式共享只写变量。(executor和executor之间不能读数据)累加器用来把executor端变量信息聚合到driver端。在driver中定义的一个变量,在executor端的每个task都会得到这个变量的一份新的副本,每个task更新这些副本的值后,传回driver端进行合并计算。1、累加器使用1)累加器定义(sparkcontext.accumulator(initialvalue)方法)2)累加器添加数据(累加器.add方法)3)累加器获取数据(累加器.value)

key_honghao的博客 1826

Spark 累加器

累加器 累加器:分布式共享只写变量。(Executor和Executor之间不能读数据) 累加器用来把Executor端变量信息聚合到Driver端。在Driver中定义的一个变量,在Executor端的每个task都会得到这个变量的一份新的副本,每个task更新这些副本的值后,传回Driver端进行合并计算。 系统累加器 ...

sj天问的博客 245

spark 广播变量和累加器使用和原理

使用 通常,当传递给Spark算子(比如map或reduce)函数在远程集群节点上执行时,它在函数中使用的所有变量的单独副本上工作。这些变量被复制到每台服务器上,对远程服务器上变量的任何更新都不会传播回driver程序。通常支持跨Tasks的读写共享变量性能比较低。也就是说如果在一个算子函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中。此时每个task只能操作自己的那份变量副本。如果多个task想要共享某个变量,那么这种方式是做不到的。 然而,Spark确实为两种常见的使用模型提供

chanyue123的博客 2189

【回顾】Spark核心编程 --- 累加器 Accumulator

文章目录1、实现原理2、案例检测3、自定义累加器 --- wordCount 1、实现原理 累加器用来把 Executor 端变量信息聚合到 Driver 端。在 Driver 程序中定义的变量,在 Executor 端的每个 Task 都会得到这个变量的一份新的副本,每个 task 更新这些副本的值后,传回 Driver 端进行 merge。 2、案例检测 package test03_rdd.accumulator import org.apache.spark.{SparkConf, Sp..

懂得一千零一种,赋予你失败的方法! 1284

Spark之累加器的概念和使用

存在的问题 在定义共享一个变量去记录计数的时候会出现一个问题 import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.rdd.RDD object Add1 { def main(args: Array[String]): Unit = { val conf: SparkConf = new SparkConf().setAppName("Add").setMaster("local[2]")

张俊杰 的博客 1014
上一篇: hbase二级索引
下一篇: Spark中repartition和coalesce的用法
Next__One
博客等级 码龄9年 14粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值