spark性能优化--极致的aggregateBykey

       在spark开发过程中,每一个算子都会影响到整体性能。对于T/p级数据聚合每一个微小的操作,都会使计算时间相差几分钟甚至小时。在计算过程中的一个原则就是尽量少的使用shuffle操作,能合并的shuffle尽量合并。

      这两天在开发的时候就犯了一个错误。需求是求出PairRdd中每个key的最大值,最小值,每个key的数量统计。一开使用的的就是最普通的算法,先cache,再求每个key的value最大值,每个key的value最小值,每个key的数量,最终生成3个pairRDD,再join到一起。这种方案共用了五次shuffle,还要做一次cache,真是一顿操作猛如虎,其实性能慢如狗。看代码:

     ...tupleRDD.cache()
      val maxOffsetRdd = tupleRdd.reduceByKey((a, b) => if (a > b) a else b)
      val minOffsetRdd = tupleRdd.reduceByKey((a, b) => if (a > b) b else a)
      val messageCount = tupleRdd.mapValues(temp => 1).reduceByKey(_ + _)
      maxOffsetRdd.join(minOffsetRdd).join(messageCount)

    对于离线计算计算,性能差一点可能也就忍了。但是对于spark stream这类操作,会影响整体运行效率。痛定思痛,最后果断改掉,改进后使用一个shuffle算子计算出最终结果,而且还不需要cache。整体性能提升了很多,今天分享出来,希望对各位(spark:火花)花友有所帮助。改进后代码:

 tupleRdd.aggregateByKey(ListBuffer[Long](0,0,0))((list, temp)=>{
        if(list(0)>temp){
          list.update(0,temp)
        }else if(list(1)<temp){
          list.update(1,temp)
        }
        list.update(2,list(2)+1L)
        list
      },(list1,list2)=>{
        if(list1(0)>list2(0)){
          list1.update(0,list2(0))
        }
        if(list1(1)<list2(1)){
          list1.update(1,list2(1))
        }
        list1.update(2,list1(2)+list2(2))
        list1
      }).mapValues(list=>(list(1),list(0),list(2)))

过程中使用了aggregateByKey算子,这个算子性能非常好,并且自由度非常强。aggregateByKey共需要传递两个方法,第一个方法是map端的一个归并操作(partition内部),结果会给每一个key生成一个容器。第二个方法是reduce端归并(partition之间相同key的合并)。效率很高是因为,很多操作再map端归并后数据量就会下降很多倍,shuffle过程需要shuffle的数量就会很少,所以性能很好。

算法讲解,先给每一个key声明一个ListBuffer[Long](0,0,0)容器(当然声明称Array会更好),第一位存储当前key最小值(因为我们的最都是正数,所以初始化用0),第二位存储当前key最大值,第三位存储当前key的计数。第一个方法:

(list, temp)=>{
        if(list(0)>temp){
          list.update(0,temp)
        }else if(list(1)<temp){
          list.update(1,temp)
        }
        list.update(2,list(2)+1L)
        list
      }

是map端合并操作,计算结果是每一个key都会有一个ListBuffer,存储相应的值。

第二个方式是计算reduce端归并操作,将partition间相同的key进行合并操作:

(list1,list2)=>{
        if(list1(0)>list2(0)){
          list1.update(0,list2(0))
        }
        if(list1(1)<list2(1)){
          list1.update(1,list2(1))
        }
        list1.update(2,list1(2)+list2(2))
        list1
      }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值