Spark中的groupByKey是否保留原始顺序?

时间:2014-06-13 13:35:43

标签: scala apache-spark

在Spark中,groupByKey函数将(K,V)对RDD转换为(K,Iterable<V>)对RDD。

然而,这个功能稳定吗?即从原始订单中保留的可迭代顺序?

例如,如果我最初读取的格式为文件:

K1;V11
K2;V21
K1;V12

我的K1的可迭代内容可能与(V12, V11)相似(因此 不保留 原始订单)或者只能是(V11, V12) }(因此 保留 原始订单)?

2 个答案:

答案 0 :(得分:13)

不,订单不会保留。 spark-shell中的示例:

scala> sc.parallelize(Seq(0->1, 0->2), 2).groupByKey.collect
res0: Array[(Int, Iterable[Int])] = Array((0,ArrayBuffer(2, 1)))

订单取决于时间,因此它可以在不同的运行之间变化。 (我在下一次跑步时得到了相反的命令。)

这里发生了什么? groupByKey通过使用HashPartitioner重新分区RDD来工作,以便密钥的所有值都在同一分区中结束。然后它在每个分区上本地执行聚合。

重新分区也称为&#34; shuffle&#34;,因为RDD的行在节点之间重新分配。随机文件从其他节点并行拉出。新分区是按照它们到达的顺序从这些部分构建的。来自最慢源的数据将位于新分区的末尾,位于groupByKey列表的末尾。

(从工作人员本身提取的数据当然是最快的。由于此处不涉及网络传输,因此这些数据被同步拉出,因此按顺序到达。(至少看起来如此。)所以复制我的实验,你需要至少2名Spark工作人员。)

来源:http://apache-spark-user-list.1001560.n3.nabble.com/Is-shuffle-quot-stable-quot-td7628.html

答案 1 :(得分:0)

Spark(和其他map reduce框架)通过分区,然后合并对数据进行排序。由于合并排序是一个稳定的操作,我猜测结果是稳定的。在查看源代码后,我发现如果spark.shuffle.spill为真,则使用外部排序,在这种情况下合并排序,这是稳定的。如果它被允许泄漏到磁盘,我不能100%确定它的作用。

来自消息来源:

private val externalSorting = SparkEnv.get.conf.getBoolean("spark.shuffle.spill", true)

分区也是一种稳定的操作,因为它没有重新排序