我正在尝试使用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并将其存储在数据库中)?
答案 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)