apache flink 中两个以上流的联合

Union of more than two streams in apache flink

我有一个关于在 Apache Flink 中合并两个以上流的架构问题。

我们有三个流,有时更多流,它们是我们使用的某种密码本 必须丰富主流。 代码簿流是压缩的 Kafka 主题。密码本是不会改变的东西 如此频繁,例如货币。主流是快速事件流。 我们的目标是用码本丰富主流。

我认为可以采用三种方法:

  1. 将所有的码本做一个并集,然后加入到主流中,并存储 丰富数据作为托管的键控状态(因此当来自 kafka 的紧凑事件过期时,我有 保存在状态中的密码本)。这是我现在厌倦的唯一方式。 将 JSON 中的 Kafka 主题消息反序列化到 POJO,例如。货币、组织单位等。 我制作了一个大包装 class CodebookData 与所有代码簿,例如:
public class CodebookData {
 private Currency currency;
 private OrganizationUnit organizationUnit
...
}

接下来我将每个 kafka 主题的传入流映射到这个包装器 class 然后建立一个联合:

DataStream<CodebookData> enrichedStream = mappedCurrency.union(mappedOrgUnit).union(mappedCustomer);

当我打印 CodebookData 时,它是这样填充的

CodebookData{
Currency{populated with data},
OrganizationUnit=null,
Customer=null
}
CodebookData{
Curenncy=null,
OrganizationUnit={populated with data},
Customer=null
}
...

我在这里停了下来,因为我有问题如何将此密码本流与主流连接并将密码本数据保存为值状态。我的密码本数据中没有唯一的外键因为每个密码本都有自己的与主流连接的外键,例如。 Currency有currencyId、organizationUnit orgID等。 Eg.I想做这样的事情

SingleOutputStreamOperator<CanonicalMessage> enrichedMainStream = mainStream
            .connect(enrichedStream)
            .keyBy(?????)
            .process(new MyKeyedCoProcessFunction());

在 MyCoProcessFunction 中,我将创建 CodebookData 类型的 ValueState。

这是完全错误的还是我可以用它做点什么,如果它是双重的,我做错了什么?

  1. 第二种方法是将一系列双输入 CoProcessFunction 运算符与每个 kafka 事件源级联,但我在某处读到这不是最佳方法。

  2. 第三种方法是我不太熟悉的广播状态。现在我看到了问题,如果我使用 RocksDb 进行检查点和保存点我不确定我是否可以使用广播状态。

我是否应该使用方法 1 中的其他方法来解决我目前正在苦苦挣扎的问题?

在许多情况下,您需要像这样执行多个独立的丰富连接,更好的模式是使用扇入/扇出方法,并并行执行所有连接。

像这样,在确保主流上的每个事件都有唯一 ID 后,您为每个事件创建 3 个或更多副本:

然后您可以通过任何适当的方式键入每个副本——货币、组织单位等(或客户、IP 地址,以及我从该图中获取的示例中的商户)——然后连接它到适当的食谱流,并独立计算每个 2 路连接。

然后将这些并行连接结果流结合在一起,keyBy 您添加到每个原始事件的随机随机数,并将结果粘合在一起。

现在在三个流的情况下,这可能过于复杂。在那种情况下,我可能只做一系列的三个双向连接,一个接一个,每次都使用 keyBy 和连接。但在某些时候,随着它们变长,以这种方式构建的管道往往 运行 出现性能/检查点问题。

https://gist.github.com/alpinegizmo/5d5f24397a6db7d8fabc1b12a15eeca6 中有一个实施此 fan-in/fan-out 模式的示例。