Spark Streaming - 如何在Iterator的分区内使用reduceByKey

时间:2016-10-07 23:41:56

标签: apache-spark apache-kafka spark-streaming

我正在尝试使用Kafka DirectStream,处理每个分区的RDD并将处理后的值写入DB。当我尝试执行reduceByKey(每个分区,没有shuffle)时,我收到以下错误。通常在驱动程序节点上,我们可以使用sc.parallelize(Iterator)来解决这个问题。但我想用火花流解决它。

value reduceByKey is not a member of Iterator[((String, String), (Int, Int))]

有没有办法在分区内对Iterator执行转换?

myKafkaDS
  .foreachRDD { rdd =>
    val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
    val commonIter = rdd.mapPartitionsWithIndex ( (i,iter) => {

      val offset = offsetRanges(i)

      val records = iter.filter(item => {
        (some_filter_condition)
      }).map(r1 => {
        // Some processing
        ((field2, field2), (field3, field4))
      })

      val records.reduceByKey((a,b) => (a._1+b._1, a._2+b._2)) // Getting reduceByKey() is not a member of Iterator
      // Code to write to DB    
      Iterator.empty // I just want to store the processed records in DB. So returning empty iterator
    })
}

是否有更优雅的方法来执行此操作(为每个分区处理kafka RDD并将其存储在数据库中)?

3 个答案:

答案 0 :(得分:1)

所以......我们不能在mapPartitionsWithIndex中使用spark变换。但是使用scala转换和减少像groupby这样的方法帮助我解决了这个问题。

答案 1 :(得分:0)

你的记录值是迭代器而不是RDD。因此,您无法在记录关系上调用reduceByKey。

答案 2 :(得分:0)

语法问题:

1)reduceByKey逻辑看起来没问题,请在语句前删除val(如果不是拼写错误)&在map:

之后附加reduceByKey()
.map(r1 => {
    // Some processing
    ((field2, field2), (field3, field4))
  }).reduceByKey((a,b) => (a._1+b._1, a._2+b._2))

2)在每次迭代结束后添加iter.next。

3)iter.empty被错误地放置了。从mapPartitionsWithIndex()

出来后放

4)为安全添加迭代器条件:

val commonIter = rdd.mapPartitionsWithIndex ((i,iter) => if (i == 0 && iter.hasNext){
....
}else iter),true)