Flink 问题之 No Watermark (Watermarks are only available if EventTime is used)

问题背景

Flink-1.17.0在集群下,获取Kafka集群数据,进行流模式实时计算,Watermarks提示:No Watermark (Watermarks are only available if EventTime is used)

source数据源是从kafka中读取topic数据,经过算子后sink到mysql表中,但在sink算子处理中,水印显示没有事件时间,导致算子无数据输出,流数据无法实时入库;

如下,因为当前SQL执行JOB的parallelism.default=2,在UI界面看到source输入源SubTasks下有两个子任务指标,其中ID=0无指标显示;

在Sink输出源下Watermarks显示任务的水印提示:No Watermark (Watermarks are only available if EventTime is used),翻译为"无水印(水印仅在使用EventTime时可用)",也就是需要用事件时间,事件时间通常是指流数据中业务字段时间或链接器的接收时间;

但是当前Job是从流数据中取的就是业务时间字段,并且是保证符合时间格式的值;

原因分析

通过查看Flink官方文档关于"Watrmark策略与Kafak连接器"内容,得知Kafka链接器会根据分区数量生成不同分区的Watemark,再合并后经过不同分区算子计算;

官方关于"Watrmark策略与Kafak连接器"说明

生成 Watermark | Apache Flink

在这种情况下,你可以使用 Flink 中可识别 Kafka 分区的 watermark 生成机制。使用此特性,将在 Kafka 消费端内部针对每个 Kafka 分区生成 watermark,并且不同分区 watermark 的合并方式与在数据流 shuffle 时的合并方式相同

同时在官方文档中有提到"处理空闲数据源"说明

生成 Watermark | Apache Flink

如果数据源中的某一个分区/分片在一段时间内未发送事件数据,则意味着 WatermarkGenerator 也不会获得任何新数据去生成 watermark。我们称这类数据源为空闲输入或空闲源。在这种情况下,当某些其他分区仍然发送事件数据的时候就会出现问题。由于下游算子 watermark 的计算方式是取所有不同的上游并行数据源 watermark 的最小值,则其 watermark 将不会发生变化。

为了解决这个问题,你可以使用 WatermarkStrategy 来检测空闲输入并将其标记为空闲状态。WatermarkStrategy 为此提供了一个工具接口:

简单来说,在Flink中kafka连接器会识别每个分片,并为每个分片创建对应Watermark水印,当上游Kafka某个分片在一段时间未发送事件数据,则对应的窗口时间内不会生成Watermark水印,则下游算子(Sink)接收上游的Watermark数据时,是按上游最小Watermark值来计算,则下游算子(Sink)不会发生变化,也就无法触发窗口算子事件;

刚好最近Kafka集群进行服务器更换,对Kafka集群机器节点做了调整,并对部署重新做了优化,有可能导致Flink从Kafka消息topic上读取到了无数据的空闲分片;

知道问题原因后,就好查找方案来解决了,Flink官方文档中明确提到:"你可以使用 WatermarkStrategy 来检测空闲输入并将其标记为空闲状态。"来解决,但这是工程代码的处理方案,我们采用SQL-Clinet执行Job,需要在执行SQL任务时,采用配置方式来处理(也可以默认在flink-config.yaml中全局配置);

查阅官方方案后,有关于table配置"table.exec.source.idle-timeout",当数据源在超时时间内无数据,则标为临时空闲并跳过当前Watermark水印,从而保证下游算子获得的是有数据的Watermark,不会让Job任务处于无数据变化,就像任务阻塞了一样;

配置 | Apache Flink

解决方案

在sql-client 窗口中,执行Job任务SQL前,先设置table.exec.source.idle-timeout=60000,表示1分钟内未收到任何流元素,则该数据表标记为临时空闲;

sql 复制代码
-- 数据源在超时时间内内没有接收到任何元素时,标记为临时空闲,这允许下游任务在空闲时推进其水印,默认为0不启用 
-- (不启用,如果kafka多分区消息不均衡或有无效分区,会导制下游任务水印无效并无法输出算子结果) 
SET table.exec.source.idle-timeout=60000;

配置上述参数后,继续执行SQL脚本JOB任务,约经过一小段时间后(1分钟),下游Sink算子的Watermark不在提示"No Watermark (Watermarks are only available if EventTime is used)",并正常显示Watermark数值;

流实时数据也能正常经过算子聚合计算后入库了;

相关推荐
呼哧呼哧.7 小时前
Spring的核心思想与注解
数据库·sql·spring
嘗_7 小时前
sql特训
数据库·sql
IT小哥哥呀8 小时前
电池制造行业数字化实施
大数据·制造·智能制造·数字化·mom·电池·信息化
Xi xi xi8 小时前
苏州唯理科技近期也正式发布了国内首款神经腕带产品
大数据·人工智能·经验分享·科技
yumgpkpm9 小时前
华为鲲鹏 Aarch64 环境下多 Oracle 、mysql数据库汇聚到Cloudera CDP7.3操作指南
大数据·数据库·mysql·华为·oracle·kafka·cloudera
橙汁味的风10 小时前
3关系型数据库的SQL语言
数据库·sql
UMI赋能企业10 小时前
制造业流程自动化提升生产力的全面分析
大数据·人工智能
TDengine (老段)10 小时前
TDengine 数学函数 FLOOR 用户手册
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
蹦跶的小羊羔12 小时前
sql数据库语法
数据库·sql
PawSQL12 小时前
企业级SQL审核工具PawSQL介绍(1) - 六大核心能力
数据库·sql·oracle