【问题标题】:How to parallelize a Flink job with Guava cache?如何使用 Guava 缓存并行化 Flink 作业?
【发布时间】:2023-03-27 03:29:01
【问题描述】:

我写了一个使用 Guava 缓存的 Flink 作业。缓存对象在 main() 函数中调用的 run() 函数中创建和使用。

有点像:

main() {
   run(some,params)
}

run() {
   //create and use Guava cache object here
}

如果我以某种程度的并行性运行这个 Flink 作业,所有并行任务会使用同一个缓存对象吗?如果没有,我怎样才能让它们都使用一个缓存?

缓存在流的 process() 函数中使用。所以就像

incoming_stream.process(new ProcessFunction() { //Use Guava Cache here })  

您可以将我的用例视为基于缓存的重复数据删除,因此我希望所有并行任务都引用单个缓存对象

【问题讨论】:

  • 从您那里显示的内容来看,我看不出任何问题。当您开始在 flink-operators(map、fold、filter 等)中使用 guava 缓存时,您会遇到麻烦。在这种情况下,您应该根据您的需要使用 flink 状态或广播状态。也许您可以更详细地解释您的用例
  • 缓存用于流的 process() 函数中。所以它就像incoming_stream.process(new ProcessFunction() { //Use Guava Cache here }) 。您可以将我的用例视为基于缓存的重复数据删除,因此我希望所有并行任务都引用单个缓存对象。

标签: caching parallel-processing guava apache-flink flink-streaming


【解决方案1】:

在 Flink 中使用 Guava 缓存通常是一种反模式。并不是说它不能工作,而是可能有一个更简单、更具可扩展性的解决方案。

使用 Flink 以完全可扩展、高性能的方式进行重复数据删除的标准方法是通过某个键(使用 keyBy)对流进行分区,然后使用键控状态来记住已经看到的键。 Flink 的键控状态由 Flink 管理,使其具有容错性和可重新扩展性,同时保持本地化。 Flink 的键控状态是一个分片键/值存储,每个实例处理键空间某些部分的所有事件。您可以保证对于每个键,同一键的所有事件都将由同一个实例处理——这就是为什么这适用于重复数据删除。

如果您需要所有并行实例都拥有某些(可能不断发展的)数据集的完整副本,这就是广播状态的用途。

【讨论】:

  • 感谢您的回答。我也觉得可能 Flink 不是为这样使用而设计的,但我想不出合适的窗口解决方案。我的用例不仅仅是去重,而是从类似事件的类别中收集一些值。这是我需要的窗口解决方案 - stackoverflow.com/questions/55328324/…
【解决方案2】:

Flink 任务运行在多个 JVM 或机器上,所以问题是如何在 JVM 之间共享对象。

通常,您可以通过RPC(通过tcp)或rest(通过http)调用从远程JVM获取对象。

或者,您可以序列化对象并将它们存储到数据库,如 reids,然后从数据库中读取并反序列化为对象。

在 Flink 中,有一种更优雅的方式来实现这一点,你可以将对象存储在 state 中,broadcast_state 可能适合你。

引入广播状态是为了支持需要将来自一个流的某些数据广播到所有下游任务的用例

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多