我正在攻读我的学士学位的最终项目,这是关于Apache Spark Streaming和Apache Flink(仅限流媒体)之间的比较,我刚刚到达"物理分区"在Flink的文档中。问题在于,在本文档中,它并没有很好地解释这两个转换是如何工作的。直接来自文档:
shuffle()
:根据统一分布随机分区元素。
rebalance()
:分区元素循环,每个分区创建相等的负载。在存在数据偏斜的情况下有助于性能优化。
两者都是自动完成的,因此我的理解是它们均匀地重新分配(shuffle()
>统一分布& rebalance()
>循环)并随机数据。然后我推断rebalance()
以更好的方式分配数据("每个分区的负载相等")因此任务必须处理相同数量的数据,但shuffle()
可能会创建更大的数据和较小的分区。 然后,在哪种情况下,您可能更愿意使用shuffle()
而不是rebalance()
?
我唯一想到的是,rebalance()
可能需要一些处理时间,所以在某些情况下,它可能会花费更多时间来进行重新平衡,而不是在未来转换中改进的时间。
我一直在寻找这个,没有人在Flink的邮件列表中谈过这个问题,但他们并没有解释shuffle()
的工作原理。
答案 0 :(得分:9)
正如文档所述,shuffle
将随机分发数据,而rebalance
将以循环方式分发数据。后者更有效率,因为您不必计算随机数。而且,根据随机性,你最终可能会得到某种不那么均匀的分布。
另一方面,rebalance
将始终开始将第一个元素发送到第一个通道。因此,如果您只有少量元素(比子任务更少的元素),那么只有一些子任务将接收元素,因为您总是开始将第一个元素发送到第一个子任务。在流式传输的情况下,这最终无关紧要,因为你通常有一个无界的输入流。
两种方法存在的实际原因是历史原因。首先介绍了shuffle
。为了使批处理的流API更加相似,我们引入了rebalance
。
答案 1 :(得分:0)
Flink的这一说法具有误导性:
在存在数据倾斜的情况下用于性能优化。
由于它用来描述rebalance
,而不是shuffle
,因此表明它是区别因素。我的理解是,如果某些项目处理缓慢而某些速度很快,则分区程序将使用下一个空闲通道将项目发送至。情况并非如此,请比较rebalance
和shuffle
的代码。 rebalance
只会添加到下一个频道,无论它有多忙。
// rebalance
nextChannelToSendTo = (nextChannelToSendTo + 1) % numberOfChannels;
// shuffle
nextChannelToSendTo = random.nextInt(numberOfChannels);
对语句的理解也有所不同:“加载”并不意味着实际的处理时间,而只是项目的数量。如果您的原始分区有偏斜(分区中的项目数量大不相同),则该操作会将项目统一分配给分区。但是,在这种情况下,这两种操作都适用。
我的结论:shuffle
和rebalance
的作用相同,但是rebalance
的处理效率略高。但是差异是如此之小,以至于您不太可能会注意到它,java.util.Random
可以在我的机器上的单个线程中生成70m随机数。