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