flink流式概念

原创
2022/02/14 00:40
阅读数 15

Flink 的 Table API  SQL 是流批统一的 API。 这意味着 Table API & SQL 在无论有限的批式输入还是无限的流式输入下,都具有相同的语义。 因为传统的关系代数以及 SQL 最开始都是为了批式处理而设计的, 关系型查询在流式场景下不如在批式场景下容易懂。

下面这些页面包含了概念、实际的限制,以及流式数据处理中的一些特定的配置。

State Management #

以流模式运行的表程序利用了Flink作为有状态流处理器的所有功能。

特别是,表程序可以配置状态后端和各种检查点选项,以处理关于状态大小和容错的不同需求。我们可以为正在运行的Table API & SQL管道取一个保存点,然后在稍后的时间点恢复应用程序的状态。

状态使用#
由于Table API和SQL程序的声明性,管道中使用的状态的位置和数量并不总是显而易见的。规划器决定是否需要状态来计算正确的结果。在给定当前优化器规则集的情况下,管道会被优化以声明尽可能少的状态。

从概念上讲,源表不会完全处于状态。实现者处理逻辑表(即动态表)。它们的状态要求取决于所使用的操作。
查询,如SELECT…从…其中只有字段投影或过滤器通常是无状态管道。但是,连接、聚合或重复数据删除等操作需要将中间结果保存在容错存储中,使用Flink的状态抽象。

有关需要多少状态以及如何限制可能不断增长的状态大小的详细信息,请参阅单个操作人员的文档。
例如,两个表的常规SQL连接要求操作符保持两个输入表完全处于状态。为了实现正确的SQL语义,运行时需要假设双方在任何时间点都可能发生匹配。Flink提供了优化的窗口和间隔连接,通过利用水印的概念来保持状态大小较小。

另一个示例是下面的查询,它计算每个会话的单击次数。

SELECT sessionId, COUNT(*) FROM clicks GROUP BY sessionId;

sessionId属性被用作分组键,连续查询为它观察的每个sessionId维护一个计数。sessionId属性会随着时间的推移而变化,sessionId值只有在会话结束时才会激活,也就是说,在一段有限的时间内。然而,连续查询并不知道sessionId的这个属性,它期望每个sessionId值都可以在任何时间点出现。它为每个观察到的sessionId值维护一个计数。因此,随着越来越多的sessionId值被观察到,查询的总状态大小不断增长。

空闲状态保留时间#
ttl Idle State Retention Time参数表定义了在删除键之前,键的状态在不更新的情况下保留多长时间。对于前面的示例查询,只要在配置的时间段内没有更新asessionId的计数就会被删除。

通过删除键的状态,连续查询将完全忘记它以前见过这个键。如果处理了一个带有键的记录,该记录的状态之前已被删除,则该记录将被当作具有相应键的第一个记录来处理。对于上面的例子,这意味着sessionId的计数将再次从0开始。

状态升级和演进#
以流模式执行的表程序旨在作为持续的查询,这意味着它们只定义一次,并作为静态的端到端管道持续评估。

在有状态管道的情况下,对查询或Flink计划器的任何更改都可能导致完全不同的执行计划。这使得有状态的升级和表程序的演进在此刻具有挑战性。社区正在努力改善这些缺点。

例如,通过添加筛选谓词,优化器可能决定重新排序连接或更改中间操作符的模式。这将防止由于拓扑改变或操作符状态中的不同列布局而从保存点恢复。

查询实现者必须确保更改前后的优化计划是兼容的。在SQL中使用EXPLAIN命令,或者在Table API中使用Table . EXPLAIN()来了解情况。

由于不断添加新的优化器规则,操作符变得更加高效和专一,升级到新的Flink版本可能会导致不兼容的计划。

目前,该框架不能保证状态可以从保存点映射到新的表操作符拓扑。

换句话说:只有当查询和Flink版本保持不变时,才支持保存点。

由于社区拒绝在补丁版本(例如,从1.13.1到1.13.2)中修改优化计划和操作员拓扑的贡献,所以应该可以安全地将Table API & SQL管道升级到更新的bug修复版本。但是,主要的和次要的升级(例如,从1.12到1.13)是不支持的。

针对这两个缺点(即修改后的查询和修改后的Flink版本),我们建议在切换到实时数据之前,检查更新后的表程序的状态是否可以再次用历史数据“预热”(即初始化)。Flink社区正在研究一种混合源,使这种切换尽可能方便。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部