Apache Flink 如何处理倾斜数据?

6
例如,我有一串大量的单词并想计算每个单词的出现次数。问题在于这些单词是倾斜的。这意味着某些单词的频率非常高,但大多数其他单词的频率很低。在Flink中,我们可以使用以下方法来解决此问题。首先,在流上执行shuffle grouping,在每个节点上以窗口时间本地计算单词计数,最后将计数更新为累积结果。
从我的另一个问题中,我知道Flink只支持键控流上的窗口,否则窗口操作将不会并行执行。
我的问题是,在Flink中是否有一种好的方法来解决这种偏斜数据的问题? enter image description here

在Storm中,我使用了“部分键分组”技术,它可以更好地处理数据倾斜。https://storm.apache.org/releases/2.0.0-SNAPSHOT/Concepts.html - Felipe
1个回答

6

目前,DataStream API并不支持原生的预聚合功能。但是,在事件时间窗口中添加类似于Combiner的功能是可能的。我认为这将是一个非常有价值的补充,但目前还没有实现。

不过,你可以自己实现这个功能。DataStream API提供了低级操作接口,类似于Storm Bolts。该接口称为OneInputStreamOperator。此操作符类型可让您完全掌控。实际上,内置操作符(如窗口操作符)也是基于此类构建的。

可以像这样应用OneInputStreamOperator

DataStream<Tuple2<String,Integer> inStream = ...
DataStream<String> outStream = inStream
  .transform("my op", BasicTypeInfo.STRING_TYPE_INFO, new MyOISO());

感谢您的帮助。我有一个问题,关于自己实现这个功能。由于Flink仅支持在键控流上进行窗口操作,否则窗口操作将无法并行执行。因此,实现不能是stream.PreAggregation(reduce_fun).keyBy().window().reduce(reduce_fun)。因为预聚合应该在窗口时间内完成。据我所知,应该是stream.PreAggregationWithWindow(reduce_fun).keyBy().reduce(reduce_fun)。然后我需要实现一个在非键控流上工作的窗口操作符。我理解得对吗? - Jun
您还可以在预聚合器中实现近似内存窗口逻辑。为此,您可以查看/复制Flink的常规窗口代码。我知道,这不是一件容易的事情,但应该是可能的。这将使第二个(最终)窗口也能并行运行,并且是更清晰的解决方案,在我看来。 - Fabian Hueske
我对你提到的更清洁的解决方案有一个不太清楚的地方,就是在预聚合之后,似乎不再需要第二个窗口了。如果出于其他原因需要,那么它是并行的。 - Jun
1
你可以按照之前的提议执行 stream.transform(new PreAgg()).keyBy().window().reduce()。在这种情况下,PreAgg 应该实现键控窗口逻辑,类似于 Flink 的窗口实现(具有固定大小的状态和可能的 LRU 逐出)。由于 PreAgg 的输入未被分区(没有 keyBy),因此键是随机分布而不会倾斜。在 PreAgg 之后,您需要按键进行分区并定义一个窗口来计算最终结果,类似于 MapReduce 中的 combiner。 - Fabian Hueske
@FabianHueske 今天是否已经实现了这个功能?如果没有,那么它是否在路线图上? - qqibrow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接