Spark RDD相当于Scala集合分区

Spark RDD相当于Scala集合分区,scala,apache-spark,scala-collections,Scala,Apache Spark,Scala Collections,这是我的一份spark工作中的一个小问题,它似乎不会引起任何问题——但每次我看到它并没有找到更好的解决方案时,它都会让我感到恼火 假设我有这样一个Scala集合: val myStuff = List(Try(2/2), Try(2/0)) 我可以使用分区将此列表划分为成功和失败: val (successes, failures) = myStuff.partition(_.isSuccess) val (successes: RDD[Try[???]], failures: RDD[T

这是我的一份spark工作中的一个小问题,它似乎不会引起任何问题——但每次我看到它并没有找到更好的解决方案时,它都会让我感到恼火

假设我有这样一个Scala集合:

val myStuff = List(Try(2/2), Try(2/0))
我可以使用分区将此列表划分为成功和失败:

val (successes, failures) =  myStuff.partition(_.isSuccess)
val (successes: RDD[Try[???]], failures: RDD[Try[???]]) = myStuff.partition(_.isSuccess)
这很好。分区的实现只遍历源集合一次以构建两个新集合。然而,使用Spark,我能设计出的最好的等价物是:

val myStuff: RDD[Try[???]] = sourceRDD.map(someOperationThatMayFail)
val successes: RDD[???] = myStuff.collect { case Success(v) => v }
val failures: RDD[Throwable] = myStuff.collect { case Failure(ex) => ex }
除了解包Try(这很好)的区别之外,还需要遍历数据两次。这很烦人

有没有更好的Spark替代方案可以在不进行多次遍历的情况下拆分RDD?i、 e.具有类似这样的签名,其中分区具有Scala collections分区而不是RDD分区的行为:

val (successes, failures) =  myStuff.partition(_.isSuccess)
val (successes: RDD[Try[???]], failures: RDD[Try[???]]) = myStuff.partition(_.isSuccess)
作为参考,我以前使用了类似下面的方法来解决这个问题。潜在的失败操作是从二进制格式中反序列化一些数据,这些失败已经变得非常有趣,需要将它们处理并保存为RDD,而不是记录下来

def someOperationThatMayFail(data: Array[Byte]): Option[MyDataType] = {
   try {
      Some(deserialize(data))
   } catch {
      case e: MyDesrializationError => {
         logger.error(e)
         None
      }
   }
}

可能还有其他解决方案,但你可以这样做:

设置:

import scala.util._
val myStuff = List(Try(2/2), Try(2/0))
val myStuffInSpark = sc.parallelize(myStuff)
执行:

val myStuffInSparkPartitioned = myStuffInSpark.aggregate((List[Try[Int]](),List[Try[Int]]()))(
  (accum, curr)=>if(curr.isSuccess) (curr :: accum._1,accum._2) else (accum._1, curr :: accum._2), 
  (first, second)=> (first._1 ++ second._1,first._2 ++ second._2))

如果您需要一个与List()大致相同的解释,请告诉我;但这只适用于小数据集,因为它需要将所有内容加载到列表中,而不是RDD@在我继续尝试其他东西之前,你能澄清一下你的问题吗。这符合您的需要和示例。您要寻找的最终签名是什么。请更新以尝试使其更清晰。你在这里展示的内容很接近,但改变了收藏的类型。这是不可能的:Josh Rosen的链接很好,尤其是这一个,因为Matei直接回答了这个问题。您最好的选择是检查主RDD中的成功。您可以使用mapPartitions至少获取每个节点的所有数据。嵌套RDD并不是正确的考虑方式(我希望拆分RDD,而不是创建RDD的RDD)。但是,我认为你是对的,这是不可能的,至少没有RDD的自定义扩展。谢谢