南宁网站推广方案如何做,企业宣传册模板图片,上海做征信服务的公司网站,wordpress导航主题1. 什么是“确定性” 先明确一下什么叫“确定性”#xff1a;对于一个“操作”来说#xff0c;如果每次给它的“输入”不变#xff0c;操作输出的“结果”也不变#xff0c;那么这个操作就是“确定性“的。通常#xff0c;我们认为批处理的操作都是确定的#xff0c;比如…1. 什么是“确定性” 先明确一下什么叫“确定性”对于一个“操作”来说如果每次给它的“输入”不变操作输出的“结果”也不变那么这个操作就是“确定性“的。通常我们认为批处理的操作都是确定的比如针对一张 clicks 表假如表中的数据没有变化无论我们执行多少次 SELECT * FROM clicks 操作它的结果始终不变。但是批处理操作并不一定总是“确定性”的如下的 SQL
SELECT * FROM clicks
WHERE cTime BETWEEN TIMESTAMPADD(MINUTE, -2, CURRENT_TIMESTAMP) AND CURRENT_TIMESTAMP;会随执行的时间点不同而呈现不同的结果clicks 表数据没有变化原因是 SQL 中的时间函数 CURRENT_TIMESTAMP 在每次执行时返回的值都不一样
另一个示例是 UUID 函数
SELECT UUID() AS uuid, * FROM clicks LIMIT 3;该函数是会为每一条记录生成唯一的 UUID所以每次执行的结果也必然是不同的。
2. 批处理中的“不确定性” 批处理中的“不确定性”都是由函数引起的上述两个示例都导致了结果的不确定性但是它们却是有差异的而且这种差异其实是非常“鲜明”的
以 CURRENT_TIMESTAMP 为代表的函数是在生成查询计划时执行的只会执行一次所以所有记录得到的是同一个值这类函数叫“动态函数”以 UUID 为代表的函数在每条记录上都会执行一次生成独立的值所以所有记录得到的是不同的值这类函数叫“不确定函数”
官方文档的解释是 在确定性函数之外存在不确定函数non-deterministic function和动态函数dynamic function, 内置的动态函数以时间函数为主两类不确定函数会在运行时即在集群执行每条记录单独计算而动态函数仅在生成查询计划时确定对应的值 运行时不再执行不同时间执行得到不同的值但同一次执行得到的值一致。 简单总结一下批处理中的“不确定性”是由不确定函数和动态函数两种函数引起的前者产生的变化值会作用在每一条记录上而后者产生的变化值仅作用在一次执行中每执行一次变化一次一次执行中记录得到值是一样的
3.流处理中的“不确定性” 和批处理相比流处理中的“不确定性”因素明显增多本质上还是因为流处理的两大核心特性导致的1. 流处理抽象出的表是“无边界的”2. 流处理的查询是“连续的”以下是流处理中几种典型的“不确定性”
补充在官方文档中讨论流上的“不确定性”时先介绍了一种情况原来在批处理中的动态函数跑到流式场景中就“降级”成了不确定函数举的例子是 函数这里文档只是想说明流处理的特性对不确定性有很大的影响但这个 Case 不是流处理中的“不确定性”的示例因为动态函数这里的CURRENT_TIMESTAMP 在批处理中本来就是“不确定性”的了。
3.1. 外部输入的不确定性 官方文档中的描述叫作 “Source 连接器回溯读取的不确定性”本人不太喜欢这个称谓因为它没有描述出“不确定性”的本质原因。实际上这种情况就是说流计算并不能对外界的数据上游数据进行强有力的控制导致及时你使用相同的时间参数和配置以流式重新读取数据时可能依然会导致结果是不一样的。其实这种情况并不能算是一种很 “Strong” 的“不确定性”在输出可能会发生变化的情况下是不会存在任何确定性操作的所以这一点不是很值得强调。
3.2. 基于处理时间的不确定性 其实这类不确定性和前面批处理中起到的 CURRENT_TIMESTAMP 情形是很类似的只是这里问题的只发生在流上主要是和基于处理时间运作的一些函数和机制有关因为区别于事件时间处理时间是基于机器的本地时间这种处理不能提供确定性。相关的依赖时间属性的操作作包括窗口聚合、Interval Join、Temporal Join 等另一个典型的操作是 Lookup Join语义上是类似基于处理时间的 Temporal Join访问的外部表如存在更新就会产生不确定性。
3.3. 基于 TTL 淘汰内部状态数据的不确定性 这也是典型的流式处理所特有的一种不确定性由于数据流的“无边界性”流计算引擎在处理双流 Join 、分组聚合这些场景时必须要在流上维持若干“状态”随着的时间的推移状态体积会不断地膨胀所以必须要设置 TTL 在规定地时间内清理这些状态这是流计算引擎必须进行的妥协。而清理 TTL 就会导致不确定性的产生这几乎无法避免。
4. 流上的“不确定性更新”NDU 流上的“不确定更新”特指流上的增量更新场景。我们知道Flink SQL 基于“在动态表上的持续查询”将流式处理“映射”成了关系表操作。对于流上发生的各种更新Flink SQL 必须要予以捕获并更新到所维持的表中用官方文档中的话说就是所有会产生增量消息的操作都必须要在 Flink 内部维护完整的状态数据在 Flink 中在整个查询管道Pipeline就是从 Source 到 Sink 的完整 DAG都依赖于更新消息的正确投递从上一下算子到下一个算子而“不确定的更新”就会导致错误
那到底什么是不确定更新呢我们知道 Flink 使用 changelog 类型的消息来描述和传导更新它包含这样几种类型(I) INSERTDDELETE-UUPDATE_BEFOREUUPDATE_AFTER对于 Insert-Only 类型的数据也就是日志型数据不存在不确定更新问题这很容易理解只有在包含 D/-U/U 这类更新消息的场景下才有可能会出现“不确定更新”问题因为此时Flink 需要根据主键去更新对应的状态数据这里涉及 Flink 如何确定主键” 的问题Flink 的处理方式是
如果能推导出主键就根据主键更新状态数据如果不能推导出主键Flink 只能完整比对现有状态中维护的所有的行才能确定如何更新或删除。此时消息不能被“不确定的列值”所干扰否则就会出现“不确定性更新”错误了