我有一个关于apache flink中两个以上流的联合的架构问题。
我们有三个甚至更多的流,它们是某种代码书,我们必须用它们来丰富主流。代码书流是压缩的Kafka主题。代码本是不会经常改变的东西,例如货币。主流是一个快速的事件流。我们的目标是用代码书丰富主流。
在我看来,有三种可能的方法:
将所有代码本合并,然后将其与主流合并,并将扩展数据存储为托管、键控状态(因此,当kafka的压缩事件过期时,我将代码本保存在状态中)。这是我现在唯一想做的事。反序列化的kafka主题消息,以json格式转换为pojo,如货币、组织单位等。我用所有代码本制作了一个大 Package 类codebookdata,例如:
public class CodebookData {
private Currency currency;
private OrganizationUnit organizationUnit
...
}
接下来,我将每个kafka主题的传入流Map到此 Package 器类,然后创建一个联合:
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、organizationunitorgid等等。我想做这样的事
SingleOutputStreamOperator<CanonicalMessage> enrichedMainStream = mainStream
.connect(enrichedStream)
.keyBy(?????)
.process(new MyKeyedCoProcessFunction());
在myprocessfunction中,我将创建codebookdata类型的valuestate。
这是完全错误的还是我可以用它做些什么,如果它是我做错的两倍?
第二种方法是将一系列的两个输入协处理函数操作符与每个kafka事件源级联,但我在某个地方读到这不是最佳方法。
第三种方法是广播状态,我不太熟悉。现在我看到了一个问题,如果我使用rocksdb进行检查点设置和保存指向,我不确定是否可以使用broadcast state。
我是否应该使用其他方法,从1号方法,我目前正在挣扎?
1条答案
按热度按时间vltsax251#
在许多情况下,您需要这样做几个独立的扩展联接,更好的模式是使用扇入/扇出方法,并行执行所有联接。
类似这样的情况,在确保主流上的每个事件都有一个唯一的id之后,您可以创建每个事件的3个或更多副本:
然后,您可以按任何适当的方式为每个副本设置密钥—货币、组织单位等(或我从中获取此图的示例中的客户、ip地址和商户)—然后将其连接到适当的cookbook流,并独立计算每个双向联接。
然后将这些并行连接结果流联合在一起,按添加到每个原始事件的随机nonce键,并将结果粘合在一起。
现在在三个流的情况下,这可能过于复杂了。在这种情况下,我可能只是做一系列的三个双向连接,一个接一个,每次都使用keyby和connect。但在某些时候,随着时间的延长,以这种方式构建的管道往往会遇到性能/检查点问题。
在中有一个实现此扇入/扇出模式的示例https://gist.github.com/alpinegizmo/5d5f24397a6db7d8f1b12a15eeca6.