如何划分RDD遵守顺序?

时间:2019-05-26 14:52:19

标签: scala apache-spark

我想将RDD划分为与我发现的不同键的数量相对应的多个分区(在这种情况下为3):

RDD:[(1,a), (1,b), (1,c), (2,d), (3,e), (3,f), (3,g), (3,h), (3,i)]

我现在要做的是具有相同键的元素将属于同一分区:

[(1,a), (1,b), (1,c)]
[(2,d)]
[(3,e), (3,f), (3,g), (3,h), (3,i)]

这就是我的分区方式

val partitionedRDD = rdd.partitionBy(new PointPartitioner(
     rdd.keys.distinct().count().asInstanceOf[Int]))

这是PoinPartitioner类

class PointPartitioner(numParts: Int) extends org.apache.spark.Partitioner{

import org.apache.spark.Partitioner
  override def numPartitions: Int = numParts

  override def getPartition(key: Any): Int = {
    key.hashCode % numPartitions
  }

  override def equals(other: Any): Boolean = other match
  {
    case dnp: PointPartitioner =>
      dnp.numPartitions == numPartitions
    case _ =>
      false
  }
}

但是,元素在各个分区之间是不平衡的。我想获得的是一个RDD分区,如下所示,其中所有分区都包含大致相同数量的元素,并遵守键的顺序:

[(1,a), (1,b), (1,c)]
[(2,d), (3,e), (3,f)]
[(3,g), (3,h), (3,i)]

我可以尝试什么?

1 个答案:

答案 0 :(得分:2)

像这样分配分区

p1 [(1,a), (1,b), (1,c)]
p2 [(2,d), (3,e), (3,f)]
p3 [(3,g), (3,h), (3,i)]

表示您想将相同的分区键分配给不同的分区(对于3,它是p2或p3)。就像数学函数一样,同一参数不能有多个值(该值取决于什么?)。

您可以做的是在分区键中添加一些内容,这将导致有更多的存储桶(有效地将一组划分为较小的组)。但是,您(实际上)无法控制Spark如何将分区放置到节点上,因此您希望位于同一节点上的数据可以跨越多个节点。

这实际上归结为您想要执行的工作。我建议考虑要获得的结果,看看是否可以在合理的权衡下(如果确实需要)提出一些智能分区键。也许您可以按字母保留值,然后使用reduceByKey而不是groupByKey之类的操作来获得最终结果?