千家信息网

怎么在Spark中自定义一个累加器

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章将为大家详细讲解有关怎么在Spark中自定义一个累加器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。累加器(accumulator)是Spar
千家信息网最后更新 2026年11月02日怎么在Spark中自定义一个累加器

这篇文章将为大家详细讲解有关怎么在Spark中自定义一个累加器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

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

累加器简单使用

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

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

结果为:

sum: 20
accum: 5

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

自定义累加器

自定义累加器类型的功能在1.X版本中就已经提供了,但是使用起来比较麻烦,在2.0版本后,累加器的易用性有了较大的改进,而且官方还提供了一个新的抽象类:AccumulatorV2来提供更加友好的自定义类型累加器的实现方式。官方同时给出了一个实现的示例:CollectionAccumulator类,这个类允许以集合的形式收集spark应用执行过程中的一些信息。例如,我们可以用这个类收集Spark处理数据时的一些细节,当然,由于累加器的值最终要汇聚到driver端,为了避免 driver端的outofmemory问题,需要对收集的信息的规模要加以控制,不宜过大。

继承AccumulatorV2类,并复写它的所有方法

package sparkimport constant.Constantimport org.apache.spark.util.AccumulatorV2import util.getFieldFromConcatStringimport util.setFieldFromConcatStringopen class SessionAccmulator : AccumulatorV2() {  private var result = Constant.SESSION_COUNT + "=0|"+      Constant.TIME_PERIOD_1s_3s + "=0|"+      Constant.TIME_PERIOD_4s_6s + "=0|"+      Constant.TIME_PERIOD_7s_9s + "=0|"+      Constant.TIME_PERIOD_10s_30s + "=0|"+      Constant.TIME_PERIOD_30s_60s + "=0|"+      Constant.TIME_PERIOD_1m_3m + "=0|"+      Constant.TIME_PERIOD_3m_10m + "=0|"+      Constant.TIME_PERIOD_10m_30m + "=0|"+      Constant.TIME_PERIOD_30m + "=0|"+      Constant.STEP_PERIOD_1_3 + "=0|"+      Constant.STEP_PERIOD_4_6 + "=0|"+      Constant.STEP_PERIOD_7_9 + "=0|"+      Constant.STEP_PERIOD_10_30 + "=0|"+      Constant.STEP_PERIOD_30_60 + "=0|"+      Constant.STEP_PERIOD_60 + "=0"  override fun value(): String {    return this.result  }  /**   * 合并数据   */  override fun merge(other: AccumulatorV2?) {    if (other == null) return else {      if (other is SessionAccmulator) {        var newResult = ""        val resultArray = arrayOf(Constant.SESSION_COUNT,Constant.TIME_PERIOD_1s_3s, Constant.TIME_PERIOD_4s_6s, Constant.TIME_PERIOD_7s_9s,            Constant.TIME_PERIOD_10s_30s, Constant.TIME_PERIOD_30s_60s, Constant.TIME_PERIOD_1m_3m,            Constant.TIME_PERIOD_3m_10m, Constant.TIME_PERIOD_10m_30m, Constant.TIME_PERIOD_30m,            Constant.STEP_PERIOD_1_3, Constant.STEP_PERIOD_4_6, Constant.STEP_PERIOD_7_9,            Constant.STEP_PERIOD_10_30, Constant.STEP_PERIOD_30_60, Constant.STEP_PERIOD_60)        resultArray.forEach {          val oldValue = other.result.getFieldFromConcatString("|", it)          if (oldValue.isNotEmpty()) {            val newValue = oldValue.toInt() + 1            //找到原因,一直在循环赋予值,debug30分钟 很烦            if (newResult.isEmpty()){              newResult = result.setFieldFromConcatString("|", it, newValue.toString())            }            //问题就在于这里,自定义没有写错,合并错了            newResult = newResult.setFieldFromConcatString("|", it, newValue.toString())          }        }        result = newResult      }    }  }  override fun copy(): AccumulatorV2 {    val sessionAccmulator = SessionAccmulator()    sessionAccmulator.result = this.result    return sessionAccmulator  }  override fun add(p0: String?) {    val v1 = this.result    val v2 = p0    if (v2.isNullOrEmpty()){      return    }else{      var newResult = ""      val oldValue = v1.getFieldFromConcatString("|", v2!!)      if (oldValue.isNotEmpty()){        val newValue = oldValue.toInt() + 1        newResult = result.setFieldFromConcatString("|", v2, newValue.toString())      }      result = newResult    }  }  override fun reset() {    val newResult = Constant.SESSION_COUNT + "=0|"+        Constant.TIME_PERIOD_1s_3s + "=0|"+        Constant.TIME_PERIOD_4s_6s + "=0|"+        Constant.TIME_PERIOD_7s_9s + "=0|"+        Constant.TIME_PERIOD_10s_30s + "=0|"+        Constant.TIME_PERIOD_30s_60s + "=0|"+        Constant.TIME_PERIOD_1m_3m + "=0|"+        Constant.TIME_PERIOD_3m_10m + "=0|"+        Constant.TIME_PERIOD_10m_30m + "=0|"+        Constant.TIME_PERIOD_30m + "=0|"+        Constant.STEP_PERIOD_1_3 + "=0|"+        Constant.STEP_PERIOD_4_6 + "=0|"+        Constant.STEP_PERIOD_7_9 + "=0|"+        Constant.STEP_PERIOD_10_30 + "=0|"+        Constant.STEP_PERIOD_30_60 + "=0|"+        Constant.STEP_PERIOD_60 + "=0"    result = newResult  }  override fun isZero(): Boolean {    val newResult = Constant.SESSION_COUNT + "=0|"+        Constant.TIME_PERIOD_1s_3s + "=0|"+        Constant.TIME_PERIOD_4s_6s + "=0|"+        Constant.TIME_PERIOD_7s_9s + "=0|"+        Constant.TIME_PERIOD_10s_30s + "=0|"+        Constant.TIME_PERIOD_30s_60s + "=0|"+        Constant.TIME_PERIOD_1m_3m + "=0|"+        Constant.TIME_PERIOD_3m_10m + "=0|"+        Constant.TIME_PERIOD_10m_30m + "=0|"+        Constant.TIME_PERIOD_30m + "=0|"+        Constant.STEP_PERIOD_1_3 + "=0|"+        Constant.STEP_PERIOD_4_6 + "=0|"+        Constant.STEP_PERIOD_7_9 + "=0|"+        Constant.STEP_PERIOD_10_30 + "=0|"+        Constant.STEP_PERIOD_30_60 + "=0|"+        Constant.STEP_PERIOD_60 + "=0"    return this.result == newResult  }}

方法介绍

value方法:获取累加器中的值

merge方法:该方法特别重要,一定要写对,这个方法是各个task的累加器进行合并的方法(下面介绍执行流程中将要用到)

iszero方法:判断是否为初始值

reset方法:重置累加器中的值

copy方法:拷贝累加器

spark中累加器的执行流程:

首先有几个task,spark engine就调用copy方法拷贝几个累加器(不注册的),然后在各个task中进行累加(注意在此过程中,被最初注册的累加器的值是不变的),执行最后将调用merge方法和各个task的结果累计器进行合并(此时被注册的累加器是初始值)

。

关于怎么在Spark中自定义一个累加器就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

累加器 方法 过程 类型 结果 信息 内容 分布式 同时 奇数 官方 拷贝 数据 文章 是在 更多 流程 版本 知识 示例 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 苏州找大状互联网科技有限公司 北京互联网科技 高科技与互联网 壕鑫互联网络科技 西安互联网科技公司 联恩商钥互联网科技有限公司 互联网巨头投资的硬核科技 中国最先进互联网科技公司 开启互联网科技时代小说 互联网实体化科技化 银川新华互联网科技职业技术培训学校图片 互联网与医疗科技 宜昌元轩互联网科技有限公司 互联网公司黑科技创始人 群盈汇互联网科技有限公司 互联网科技资金流入 富国互联网科技002692 全球科技与互联网公司市值变化 云南互联网科技学费 重庆科技产业互联网有哪些 亿人帮互联网科技有限公司 玖二柒互联网科技公司待遇 北京华百购互联网科技有限公司 互联网企业和科技型企业 厦门千工互联网科技有限公司 消费医药和互联网科技 民营互联网公司国防科技 启辰互联网科技 互联网时代高科技布局 河南商务圈互联网科技有限公司
0