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数值;

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

相关推荐
小牛头#4 小时前
clickhouse 各个引擎适用的场景
大数据·clickhouse·机器学习
lifallen6 小时前
Paimon LSM Tree Compaction 策略
java·大数据·数据结构·数据库·算法·lsm-tree
元宇宙时间6 小时前
全球发展币GDEV:从中国出发,走向全球的数字发展合作蓝图
大数据·人工智能·去中心化·区块链
张先shen8 小时前
Elasticsearch RESTful API入门:基础搜索与查询DSL
大数据·spring boot·elasticsearch·搜索引擎·全文检索·restful
{⌐■_■}10 小时前
【Kafka】登录日志处理的三次阶梯式优化实践:从同步写入到Kafka多分区批处理
数据库·分布式·mysql·kafka·go
isNotNullX10 小时前
数据中台架构解析:湖仓一体的实战设计
java·大数据·数据库·架构·spark
CodeWithMe10 小时前
【Note】《Kafka: The Definitive Guide》 第九章:Kafka 管理与运维实战
运维·分布式·kafka
sql2008help10 小时前
1-Kafka介绍及常见应用场景
分布式·kafka
数据库安全13 小时前
首批|美创智能数据安全分类分级平台获CCIA“网络安全新产品”
大数据·人工智能·web安全
袋鼠云数栈14 小时前
使用自然语言体验对话式MySQL数据库运维
大数据·运维·数据库·后端·mysql·ai·数据治理·数栈·data+ai