coalesce 和 repartition 有什么不同?
coalesce
和 repartition
这两个算子都是用于数据重分布、调整任务的并行度,以便提升 CPU 的使用效率。
在实际开发过程中,我们可以用某个 RDD 调用 repartition(n)
,来增大或减少 RDD 的并行度,其中 n 必须是大于 0 的正整数。
val lineRDD:RDD[String] = sc.textFile("./data/words.txt",2)
lineRDD.partitions.length // 2
lineRDD.repartion(4)
lineRDD.partitions.length // 4
lineRDD.repartition(3)
lineRDD.partition.length //3
从上述代码来看,repartition
算子非常灵活,可以随意的调整 RDD 的并行度,用法简单。
但是它有个致命的缺陷,无论是增加分区数还是减少分区数,repartition 算子都是通过 shuffle 实现的,shuffle 就是把数据打乱,将数据重新分发,可以结合下面这张图理解。
shuffle 势必就会导致磁盘 IO 和 网络 IO 开销较大,性能也就会下降。
那有没有在减少分区时,不产生 shuffle 的算子?相信你也猜到了,就是 coalesce。
coalesce 在用法上和 repartition 一致,coalesce 会多一个参数 coalesce(n,shuffle) ,这个 shuffle 是一个 Boolean 类型,表示是否开启 shuffle 。
如果你深入到源码中去看,其实 repartion(n) = coalesce(n,true)
, 也可以看到repartiton(n)
的底层调的就是 coalesce(n,true)
函数。
coalesce 既可以开启 shuffle ,也可以不开启 shuffle 。但是,如果你是增加分区,也就是调大 RDD 的并行度,必须通过开启 shuffle 来实现。
那么在减少分区时,可以选择使用 coalesce(n,false)
实现,因为他是通过把同一个 Executor 内的不同数据分区进行合并,如此一来,不需要跨 Executor 、跨节点分发数据,也就不会引入 shuffle 。可以结合下面这张图理解:
coalesce 和 repartition 区别:
coalesce shuffle 机制可以配置,但只针对降低 RDD 的并行度这种情况,如果增加并行度必须通过 shuffle 实现
repartition 的底层是调用 coalesce(n,true)
实现的,无论是增加或减少并行度,都会产生shuffle。