在Spark中,groupByKey函数将(K,V)
对RDD转换为(K,Iterable<V>)
对RDD。
然而,这个功能稳定吗?即从原始订单中保留的可迭代顺序?
例如,如果我最初读取的格式为文件:
K1;V11
K2;V21
K1;V12
我的K1
的可迭代内容可能与(V12, V11)
相似(因此 不保留 原始订单)或者只能是(V11, V12)
}(因此 保留 原始订单)?
答案 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)
分区也是一种稳定的操作,因为它没有重新排序