【spark】spark编程坑——foreach的坑


前言

在开发时发现一个事,rdd有foreach方法,rdd.collect之后也有foreach,这两个方法却大不一样。

1.1、代码示例

代码如下(示例):

 def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder
      .master("local[*]")
      .appName("test")
      .getOrCreate()
    val sc = spark.sparkContext;
    val value = sc.makeRDD(List(1, 2, 3, 4),2)
      .map(_*2);
    value.collect().foreach(println);
    println("**********")
    value.foreach(println)
    sc.stop()
    }

输出:

2
4
6
8
**********
6
8
2
4

在本地为多线程(local[*])执行的时候,并且分区为2个以上的时候,rdd.foreach方法打印出来的数据顺序乱了!~

2.1、解释

在这里插入图片描述
如图所示,rdd.foreach方法在执行的过程中的打印方法是在Executor中执行的,每个Executor在执行完自己的逻辑之后就执行foreach进行打印,因此在本地多线程执行的时候,可能List(3,4)是有可能先执行完成,所以会存在顺序错乱的情况。
多线程,多分区才会有这种情况
value.collect().foreach(println)这种写法的print是在数据采集到Driver之后,在Driver端打印的。所以顺序不会乱。

2.1 代码示例

RDD中集合有1,2,3,4,想通过foreach来进行累加,但是打印出来的结果却是0。这个就是累加器的坑。大家多多参考。


  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder
      .master("local[*]")
      .appName("test")
      .getOrCreate()
    val sc = spark.sparkContext;

    val value = sc.makeRDD(List(1, 2, 3, 4))

    var sum = 0;
    value.foreach(num=>{
      sum+=num;
    })
    println("总和为:"+sum)
    sc.stop()

}

输出:

总和为:0

在普通的java编程中或者其他语言的变成中, 这种写法是没有问题的,但是在RDD中,有Driver和Executor的概念,RDD的计算是在Executor中进行的。然而sum确是在Driver中产生的。
在这里插入图片描述
如上图所示,sum=0 会传递到两个Executor中,进行累加,两个Executor的sum没有各自累加自己的数据,但是sum的值并没有回调给Driver中,因此,Driver中的sum一直是0。
因此spark数据结构中有一个叫累加器。通过累加器即可完成此功能,代码如下:

  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder
      .master("local[*]")
      .appName("test")
      .getOrCreate()
    val sc = spark.sparkContext;
    val value = sc.makeRDD(List(1, 2, 3, 4))
    val sum =    sc.longAccumulator("sum");
    value.foreach(num=>{
      sum.add(num)
    })
    println("总和为:"+sum.value)
    sc.stop()
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叁滴水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值