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累加器的相关内容,首先介绍了累加器的简单使用,然后向大家分享了自定义累加器的实例代码,需要的朋友可以参考下。 立即下载

相关推荐

基于决策树的英雄联盟比赛胜负预测(含完整代码)

在代码中设置随机种子(例如 RANDOM_SEED = 2024)的主要目的是为了确保每次运行代码时,随机过程的结果是一致的。通过绘制不同参数组合下的准确率图,直观地展示了参数对模型性能的影响,帮助读者更好地理解和选择合适的参数。通过设置相同的随机种子(伪随机数),可以确保每次运行代码时,随机数生成器生成的随机数序列是相同的。如果在开发过程中遇到问题,设置固定的随机种子可以帮助你更容易地定位问题,因为每次运行代码时的数据和结果都是一样的。在科学研究和实验中,结果的可重复性是非常重要的。

oisflo的博客 1919

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

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

有所谓的博客 754

关于基于Midas Civil API的二次开发——PyMiMi

现在写了第一条博客,希望是一个好的开始,能够每天抽出一两个小时或者更多的时间来写写代码,研究研究。我发现在我的工作中存在着大量的重复性工作,对于文档的开发是好办的,毕竟网上有现成库,只需要pip一下拿来用就好,但是对于Midas而言,在24版本之前官方都是没有一个可以使用的接口的,可能mct文件算半个?

ManiacsTraitor的博客 1848

自定义Spark累加器

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

阿拉修 1231

从入门到精通:dirmap 高级 Web 目录扫描实战指南

本文提供了一份从环境搭建到高级配置的dirmap Web目录扫描实战指南。详细解析了工具安装、核心配置文件dirmap.conf的深度调优,包括递归扫描、四种扫描模式(字典、爆破、爬虫、Fuzz)的实战应用,并演示了分阶段资产发现的完整工作流程,帮助安全人员高效发现隐藏目录与敏感文件。

rnn9storyteller的博客 480

Python实战:5分钟搞定高德地图API批量地址转经纬度(附完整代码)

本文提供了一套完整的Python解决方案,利用高德地图Web服务API,实现批量地址到经纬度坐标的自动化转换。文章包含从API申请、核心代码编写到错误处理与性能优化的全流程实战指南,并附赠数据可视化方法,帮助数据分析师和开发者快速提升地理信息处理效率。

weixin_29047919的博客 582

spark 累加器

spark 累加器

qq_43192537的博客 3020

基于Python实现身份证信息识别

身份证是一种重要的证件,包含了个人的基本信息,如姓名、性别、出生日期、住址等。在实际应用中,有时需要对身份证进行自动化的识别,以提高工作效率和准确性。本文将介绍如何使用Python实现身份证信息的识别,通过图像预处理、OCR技术和解析算法,实现对身份证号码和其他信息的提取和解析。

商务合作 / 项目定制 / 学习交流。个人vx:lovely_wml 1万+

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

【即插即用模块】卷积篇 | TCSVT 2025 | MFACB:多尺度膨胀融合,快速扩大感受野,多尺度特征精准捕捉!

本文提出了一种新型多尺度融合膨胀卷积模块MFACB,用于增强语义分割任务中的特征表达能力。该模块通过三分支串联膨胀卷积结构快速扩大感受野,采用双路径融合机制(基础信息路径+多尺度信息路径)实现高效上下文聚合。相比传统卷积块,MFACB在保持轻量化的同时显著提升了多尺度特征捕捉能力,实验表明其性能优于基础残差块。该模块支持自定义膨胀率和步长调整,可灵活嵌入不同网络阶段,适用于需要特征增强的视觉任务。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 310

手把手教你学simulink(26.8)--控制算法场景示例:基于强化学习的无人机姿态稳定控制系统

首先,我们需要定义无人机的姿态稳定控制环境。环境包括无人机的状态(姿态角、角速度等)和动作(电机转速)。我们还需要定义奖励函数,用于评估控制器的表现。matlab深色版本% 定义环境% 定义状态空间% 12个状态变量% 定义动作空间% 电机转速范围奖励函数用于评估控制器的表现。我们可以根据无人机的姿态误差、角速度误差以及控制输入的变化率来设计奖励函数。具体来说,当无人机的姿态接近设定值时,给予正奖励;当姿态误差较大或控制输入变化剧烈时,给予负奖励。matlab深色版本。

MHD0815的博客 494

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

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

Ran_记忆犹新的博客 5328

2万字大厂面经:小米嵌入式面试题及参考答案(持续更新)

BIOS (Basic Input/Output System) 是一种存储在ROM中的固件程序,它为计算机提供了最基础的硬件初始化和服务。BIOS主要存在于传统的x86架构计算机中。嵌入式系统的启动流程取决于具体的硬件平台和所采用的操作系统。复位阶段:当系统通电或复位时,CPU进入复位状态。硬件初始化:CPU和必要的硬件设备(如内存控制器)被初始化。加载引导加载程序:引导加载程序(如U-Boot)被加载到内存中。执行引导加载程序:引导加载程序开始执行,初始化更多的硬件设备,并检测存储介质。

大模型大数据攻城狮的专栏 2529

Spark之累加器

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

weixin_42796403的博客 598

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

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

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

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

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

程序猿丶HLK 1302

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

大数据开发之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、付费专栏及课程。

余额充值