为什么在具有相同键的两个RDD上应用相同的HashPartitioner并不能平均分区

时间:2017-05-17 19:35:34

标签: apache-spark join rdd partitioning shuffle

我有两个具有相同键和不同值的RDD。 我打电话给他们两个.partitionBy(partitioner) 然后我加入他们:

val partitioner = new HashPartitioner(partitions = 4)

val a = spark.sparkContext.makeRDD(Seq(
  (1, "A"), (2, "B"), (3, "C"), (4, "D"), (5, "E"), (6, "F"), (7, "G"), (8, "H")
)).partitionBy(partitioner)

val b = spark.sparkContext.makeRDD(Seq(
  (1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e"), (6, "f"), (7, "g"), (8, "h")
)).partitionBy(partitioner)

println("A:")
a.foreachPartition(p => {
  p.foreach(t => print(t + " "))
  println()
})

println("B:")
b.foreachPartition(p => {
  p.foreach(t => print(t + " "))
  println()
})

println("Join:")
a.join(b, partitioner)
  .foreachPartition(p => {
    p.foreach(t => print(t + " "))
    println()
})

我明白了:

A:
(2,B) (3,C) (4,D) (6,F) (7,G) 
(8,H) (1,A) 
(5,E) 

B:
(3,c) (7,g) 
(1,a) (5,e) 
(2,b) (6,f) 
(4,d) (8,h) 

Join:
(6,(F,f)) (1,(A,a)) (2,(B,b)) (5,(E,e)) (4,(D,d)) (8,(H,h)) 
(3,(C,c)) (7,(G,g))

所以第一个问题是为什么A和B分区不同以及为什么joinRDD与它们不同?

1 个答案:

答案 0 :(得分:1)

在所有情况下,分区完全相同。问题是您使用的方法。请记住,每个分区都在一个单独的线程中处理。如果多次运行此代码,您将看到输出实际上是非确定性的。

尝试这样的例子:

a.glom.collect.map(_.mkString(" ")).foreach(println)
(4,D) (8,H)
(1,A) (5,E)
(2,B) (6,F)
(3,C) (7,G)
b.glom.collect.map(_.mkString(" ")).foreach(println)
(4,d) (8,h)
(1,a) (5,e)
(2,b) (6,f)
(3,c) (7,g)
a.join(b).glom.collect.map(_.mkString(" ")).foreach(println)
(4,(D,d)) (8,(H,h))
(1,(A,a)) (5,(E,e))
(6,(F,f)) (2,(B,b))
(3,(C,c)) (7,(G,g))

请注意,如果在非local上下文中执行,则每个分区中的值的顺序仍然可以是非确定性的,但每个分区的内容将与上面显示的相同。