我尝试通过ID连接两个数据流,发现有两个API集可以这样做,
- https://ci.apache.org/projects/flink/flink-docs-release-1.12/dev/stream/operators/joining.html
- https://ci.apache.org/projects/flink/flink-docs-release-1.12/dev/table/sql/queries.html#joins
看来他们两个都能完成这项工作。
所以我的问题是:
- 主要区别是什么?如何选择
- 如果我加入流A和流B,并且两者都有很多记录(例如A:10000,B: 20000(,是彼此比较的不同流中的所有记录一个接一个?比较总数为10000x20000
- 此外,是否存在任何情况(可能是网络问题(,流B是延迟,则流B中的一些记录不会与流进行比较A
谢谢。
主要区别是什么?如何选择?
有几种不同的API可以用来实现Flink的联接。您可以在Ververica分享的Apache Flink开发人员培训材料中找到不同方法的调查,网址为https://training.ververica.com/decks/joins/?mode=presenter(在登记表后面(。免责声明:这些培训材料是我写的。
总结:
用于实现流连接的底层构建块是KeyedCoProcessFunction
。在具有完全控制很有价值的特殊情况下,直接使用它是有意义的,但对于大多数目的,您最好使用更高级别的API。
数据集API提供了实现为哈希联接、排序-合并联接和广播联接的批处理联接。这种API已被软性弃用,最终将被绑定流和Flink的关系API(SQL/Table(的组合所取代。
DataStream API只提供一些时间窗口和间隔联接。它不支持任何可能需要无限状态保留的联接。
SQL/Table API支持广泛的批处理和流连接:
流式处理&批次
- 时间窗口和区间INNER+OUTER JOIN
- 无窗INNER+OUTER JOIN
仅限流
- 时间版本的INNER JOIN
- 外部查找INNER JOIN
SQL优化器能够推断由于时间限制而不再需要的状态。但一些流连接确实有可能需要无界状态才能产生完全正确的结果;可以设置状态保留策略来清除不太可能需要的过时条目。
请注意,表API与DataStream API完全可互操作。我会尽可能使用SQL/Table联接,因为它们实现起来更简单,而且优化得很好。
如果我加入流A和流B,并且两者都有很多记录(例如A:10000,B:20000(,那么不同流中的所有记录是否都会逐一进行比较?比较总数为10000x20000?
Flink支持等密钥联接,其中对于某些特定密钥,您希望联接流A和流B中具有相同密钥值的记录。如果来自A的10000条记录和来自B的20000条记录都具有相同的关键字,那么是的,A和B的无约束联接将产生10000x20000个结果。
但我不相信你的意思。Flink将在其托管状态下实现分布式哈希表,这些哈希表将在集群中进行分片(按键(。例如,当一个新记录从流a到达时,它将被散列到a的构建侧哈希表中,而B的相应哈希表将被探测以找到匹配的记录,并且所有合适的结果都将被发出。
请注意,这是并行进行的。但是,来自A和B的特定密钥的所有事件都将由同一实例处理。
此外,是否存在任何情况(可能是网络问题(,流B被延迟,然后流B中的一些记录没有与流A进行比较?
如果将事件时间处理与SQL/Table API提供的时间窗口或间隔联接相结合,则不会考虑后期事件(由水印确定(,并且结果将不完整。使用DataStream API,可以实现对后期事件的特殊处理,例如将它们发送到侧输出,或者收回和更新结果。
对于没有时间约束的联接,无论延迟事件何时到达,都会正常处理。结果(最终(是完整的。