大数据-121 - Flink Time Watermark 详解 附带示例详解
点一下关注吧!!!非常感谢!!持续更新!!!
目前已经更新到了:
- Hadoop(已更完)
- HDFS(已更完)
- MapReduce(已更完)
- Hive(已更完)
- Flume(已更完)
- Sqoop(已更完)
- Zookeeper(已更完)
- HBase(已更完)
- Redis (已更完)
- Kafka(已更完)
- Spark(已更完)
- Flink(正在更新!)
章节内容
上节我们完成了如下的内容:
- 滑动窗口:时间驱动、事件驱动
- 会话窗口:时间驱动、事件驱动

Time
在Flink的流式处理中,会涉及到时间的不同概念, 如下图所示:

- EventTime[事件时间]:事件发生的时间,例如:点击网站上的某个链接的时间,每一条日志都会记录自己的生成时间,如果EventTime为基准来定义时间窗口那将形成EventTimeWindow,要求消息本身就应该携带EventTime
- IngestionTime[摄入时间]:数据进入Flink时间,如某个Flink节点SourceOperator接收到数据的时间,例如:某个Source消费到Kafka中的数据,如果以IngesingTime为基准来定义时间窗口那将形成IngestingTimeWindow,以Source的SystemTime为准
- ProcessingTime[处理时间]:某个Flink节点执行某个Operation的时间,例如:TimeWindow处理数据时的系统时间,默认时间的属性就是ProcessingTime。如果以ProcessingTime基准来定义时间窗口将形成ProcessingTimeWindow,以Operator的SystemTime为准
在Flink的流式处理中,绝大部分的业务都会使用EventTime,一般只在EventTime无法使用时,才会被迫使用ProcessingTime或者IngestionTime。
如果使用EventTime,那么需要引入EventTime的事件属性,引入方式如下所示:
# 设置使用事件时间
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
基本概念
在 Apache Flink 中,Time Watermark(时间水印)是处理事件时间(Event Time)流处理的核心概念之一。它用于解决乱序事件的问题,帮助系统正确地按照事件发生的时间顺序进行处理。下面是详细解释:
事件时间(Event Time)和处理时间(Processing Time)
事件时间(Event Time):事件生成时所关联的时间戳。例如,一条日志记录的生成时间。
处理时间(Processing Time):事件到达 Flink 处理节点时的时间。这取决于系统的时间。
在实际的流处理中,事件的到达顺序可能会与它们的事件时间不一致,因为网络延迟、分布式系统等原因导致事件乱序。因此,使用事件时间而非处理时间来处理流数据更能准确反映数据的真实生成顺序。
乱序事件
乱序事件指的是数据流中的事件没有按照事件时间的顺序进入流处理系统。例如,事件A的事件时间是 12:00:01,事件B是 12:00:02,但事件B可能会比事件A先到达处理系统。
为了处理这种乱序问题,Flink 引入了 Watermark 机制。
什么是 Watermark
Watermark 是一个特殊的标志,它用于告诉 Flink 数据流中事件的进展情况。简单来说,Watermark 是 Flink 中估计的“当前时间”,表示所有早于该时间戳的事件都已经到达。
Watermark 的定义
Flink 认为当前时间在 Watermark 时间戳之前的所有事件已经接收完毕,不再期待有早于该时间戳的事件。
当 Watermark 时间戳更新时,系统可以触发基于事件时间的窗口操作,比如窗口计算、聚合等。
示例: 假设 Watermark 当前的值是 12:00:00,那么 Flink 认为 12:00:00 之前的事件已经全部到达,不会再有更早的事件来临。这时系统可以处理 12:00:00 之前的事件并触发窗口计算。
Watermark 生成方式
Watermark 可以通过自定义来生成,也可以使用内置策略。在常见情况下,Watermark 生成方式有两种:
a. 固定延迟策略(Fixed Delay)
最简单的 Watermark 生成方式是引入固定的延迟。例如,假设延迟 5 秒生成 Watermark,那么每个事件时间戳减去 5 秒就是当前的 Watermark。
b. 周期性生成 Watermark
Flink 允许 Watermark 定期生成,可以通过定期检查数据流中的最大时间戳来生成新的 Watermark。
数据延迟问题
示例1
现在假设,你正在去往地下停车场的路上,并且打算用手机点一份外卖。
选好了外卖之后,你就用在线支付功能付款了,这个时候是 11点50分。
但是这时,你走进了地下停车库,而这里没有手机信号,因此外卖的在线支付并没有立刻成功,而支付系统一直在Retry这个操作。
当你找到了自己的车并开出停车场的时候,已经是 12点05分了,而支付数据的处理时间是 12点05 分。
一般在实际开发中会以事件时间作为计算标准。
示例2

- 一条日志进入Flink的事件为 2024-07-27 10:00:01 摄入时间
- 到达Window系统的时间是 2024-07-27 10:00:02 处理时间
- 日志内容为:2024-07-27 09:59:5- INFO Fail Over 事件时间
对于业务来说,要统计1小时内的故障日志的个数,哪个时间最有意义?当然是事件时间。
EventTime,因为我们要根据日志的生成时间进行统计。
示例3
某APP记录用户的所有点击行为,并回传日志,(在网络不好的情况下,先保存本地,延后回传)。
A用户在 11:02 对APP进行操作,B用户在 11:03 操作了APP。
但是A用户的网络太不稳定,回传日志延迟了,导致我们服务端先接受到B的消息,再接收到A的消息,消息乱序了。
示例4
在实际环境中,经常会出现,因为网络原因,数据有可能会延迟一会儿才到达Flink实时处理系统,我们先来设想一下下面的场景:

- 使用时间窗口来统计10分钟内的用户流量
- 有一个时间窗口:开始时间 2024-07-27 10:00:00,结束时间 2024-07-27 10:10:00
- 有一个数据,因为网络延迟:事件发生的时间为:2024-07-27 10:10:00,但进入到窗口的事件为:2024-07-27 10:10:02 延迟2秒
这种处理方式,根据消息进入到Window时间,来进行计算,在网络有延迟的时候,会引起计算误差。
如何解决
使用水印来解决网络延迟的问题。
通过上面的例子,我们知道,在进行数据处理的时候应该按照事件时间进行处理,也就是窗口应该要考虑到事件时间。
但是窗口不能无限的一直等待延迟数据的到来,需要有一个触发窗口计算的进制,也就是我们接下来要学的Watermark水位线/水印机制。
WaterMark
水印(Watermark)就是一个时间戳,Flink可以给数据流添加水印,可以理解为:
- 收到一条消息后,额外给这个消息添加一个时间字段,这就是添加水印。
- 水印并不影响原有EventTime事件时间
- 当数据流添加水印后,按照水印时间来触发窗口计算:也就是Watermark水印是用来触发窗口计算的
- 一般会设置水印时间,比事件时间小几秒钟,表示最大允许数据延迟到达多久(即水印时间 = 事件时间 - 允许延迟时间)
- 当接收到的 水印时间 >= 窗口结束时间,则触发计算,如等到一条数据的水印时间为 10:10:03 >= 10:10:00 才触发计算,也就是要等到事件为 10:10:03的数据到来才触发计算

解决总结
Watermark是用来解决延迟数据的问题,如窗口:10:00:00 ~ 10:10:00
而数据到达的顺序是:A 10:10:00,B 10:09:58
如果没有Watermark,那么A数据将会触发窗口计算,B数据来了窗口已经关闭,则该数据丢失。
如果有了 Watermark,设置允许数据迟到的阈值为3秒。
那么该窗口的结束条件则为水印:水印时间 >= 窗口结束时间 10:10:00,也就是需要一条数据的水印事件=10:10:00
而水印时间10:10:00 = 事件时间 - 延迟时间 3 秒
也就是需要有一条事件为10:10:03的数据到来,才会触发真正的计算。
而上面的A 10:10:00,B 10:09:58 都不会触发计算,也就是会被窗口包含,直到10:10:03的数据到来才会计算窗口 10:00:00 - 10:10:00 的数据。
Watermark
实现步骤
- 获取数据源
- 转化
- 声明水印(Watermark)
- 分组聚合,调用Window操作
- 保存处理结果
注意事项
当使用 EventTimeWindow时,所有的Window在EventTime的时间轴上进行划分,也就是说,在Window启动后,会根据初始的EventTime时间每隔一段时间划分一个窗口,如果Window大小是3秒,那么1分钟内会把Window划分为如下的形式:
[00:00:00,00:00:03)
[00:00:03,00:00:06)
[00:00:03,00:00:09)
[00:00:03,00:00:12)
[00:00:03,00:00:15)
[00:00:03,00:00:18)
[00:00:03,00:00:21)
[00:00:03,00:00:24)
- 窗口是左闭右开,形式为为:[window_start_time, window_end_time)
- Window的设定基于第一条消息的事件时间,也就是说,Window会一直按照指定的时间间隔进行划分,不论这个Window中没有数据,EventTime 在这个Window期间的数据会进入这个Window
- Window会不断产生,属于这个Window范围的数据会不断加入到Window中,所有未被触发的Window都会等待出发,只要Window还没出发,属于这个Window范围的数据就会一直被加入到Window中,直到Window被处罚才会停止数据的追加,而当Window触发之后才接收到属于被触发Window的数据会被丢弃。
- Window会在以下的条件满足时才会被处罚执行:(1)在[window_start_time, window_end_time)窗口中有数据存在,(2)Watermark时间 >= window_end_time
一般会设置水印时间,比事件时间小几秒钟,表示最大允许数据延迟到达是多久:水印时间=事件时间-允许延迟时间。
当接收到水印时间 >= 窗口结束时间 且 窗口内有数据,则触发计算:事件时间 - 允许延迟时间 >= 窗口结束时间 或 事件时间 >= 窗口结束时间 + 允许延迟时间
相关文章:
大数据-121 - Flink Time Watermark 详解 附带示例详解
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
国行 iPhone 15 Pro 开启苹果 Apple Intelligence 教程
一、前言苹果在 iOS 18.1 测试版上正式开启了 Apple Intelligence 的内测,但国行设备因政策原因不支持,且国行设备在硬件上被锁定。不过,我们可以通过一些方法来破解国行 iPhone 15 Pro,使其能够开启 Apple Intelligence。 以下是…...
conda、anaconda、pip、torch、pytorch、tensorflow到底是什么东西?(转载自本人的知乎回答)
转载自本人的知乎回答(截止2024年9月,1700赞同,2400收藏) https://www.zhihu.com/question/566592612/answer/3063465880 如果你是一个大四的CS准研究生回去补基础课,假如是科班CS甚至科班EE的话那你基础也太差了。你…...
数据库系列之GaussDB数据库中逻辑对象关系简析
初次接触openGauss或GaussDB数据库的逻辑对象,被其中的表空间、数据库、schema和用户之间的关系,以及授权管理困惑住了,与熟悉的MySQL数据库的逻辑对象又有明显的不同。本文旨在简要梳理下GaussDB数据库逻辑对象之间的关系,以加深…...
如何进行不同数据库的集群操作?--从部署谈起,今天来看MySQL和NoSql数据库Redis的集群
篇幅较长,主要分为mysql和Redis两部分。找想要的部分可见目录食用。。 目录 什么是集群?为什么要集群? 1.1 数据库主要分为两大类:关系型数据库与 NoSQL 数据库 1.2 为什么还要用 NoSQL 数据库呢? ----------------…...
第 6 章图像聚类
本章将介绍几种聚类方法,并展示如何利用它们对图像进行聚类,从而寻找相似的图像组。聚类可以用于识别、划分图像数据集,组织与导航。此外,我们还会对聚类后的图像进行相似性可视化。 6.1 K-means聚类 K-means 是一种将输入数据划…...
HC-SR501人体红外传感器详解(STM32)
目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 body_hw.h文件 body_hw.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 HC-SR501人体红外模块是基于红外线技术的自动控制模块,采用德国原装进口LHI77…...
关于武汉芯景科技有限公司的IIC电平转换芯片XJ9517开发指南(兼容PCF9517)
一、芯片引脚介绍 1.芯片引脚 2.引脚描述 二、系统结构图 三、功能描述 1.电平转换 2.芯片使能/失能 EN 引脚为高电平有效,内部上拉至 VCC(B),允许用户选择中继器何时有效。这可用于在上电时隔离行为不良的从机,直到…...
C语言:scanf()、getchar()、gets()
一、gets() gets()能吸收空格和换行,因此输入后,对输出要去除空格 和换行\n; #include <stdio.h> #include <string.h> int main() {char str[1000];int count0;gets(str);for(int i0;i<strlen(str);i)count;printf("%s\n",str…...
基于MATLAB的全景图像拼接系统实现
简要的论文框架和技术思路 摘要 本文深入探讨了基于MATLAB平台的块匹配全景图像拼接系统的设计与实现。通过详细解析SIFT/SURF特征提取、RANSAC变换估计、APAP局部对齐、图割算法拼接缝选择及multi-band blending图像融合等关键技术,构建了高效且高质量的全景图像…...
AI模型“减肥”风潮:量化究竟带来了什么?
量化对大模型的影响是什么 ©作者|YXFFF 来源|神州问学 引言 大模型在NLP和CV领域的广泛应用中展现了强大的能力,但随着模型规模的扩大,对计算和存储资源的需求也急剧增加,特别是在资源受限的设备上面临挑战。量化技术通过将模型参数和…...
第四届“长城杯”网络安全大赛 暨京津冀网络安全技能竞赛(初赛) 全方向 题解WriteUp
战队名称:TeamGipsy 战队排名:18 SQLUP 题目描述:a website developed by a novice developer. 开题,是个登录界面。 账号admin,随便什么密码都能登录 点击头像可以进行文件上传 先简单上传个木马试试 测一下&…...
ETCD的备份和恢复
一、引言 ETCD是一个高度可用的键值存储系统,被广泛应用于Kubernetes等分布式系统中以存储关键配置数据和服务发现信息。由于ETCD的重要性,确保其数据的安全性和可靠性至关重要。本文将介绍ETCD备份与恢复的基础知识、常用方法及最佳实践。 二、概述 …...
Linux Makefile文本处理函数知识详解
1.Makefile函数 GNU make 提供了大量的函数用来处理文件名、变量、文本和命令。通过这些函数,用户可以节省很多精力,编写出更加灵活和健壮的Makefile。函数的使用和变量引用的展开方式相同: $(function arguments)${function arguments}关于…...
Rust的数据类型
【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学,之一 -CSDN博客 Rust到底值不值得学,之二-CSDN博客 3.5 数据类型的定义和分类 在Rust…...
如何在vim中批量注释和取消注释
一、批量注释 首先在你需要注释的初始所在行在命令模式下输入CTRL v,然后按下HJKL来控制方向(不能使用键盘上的箭头方向键): 然后输入 shifti: 输入两个斜杠然后加exc就可以完成批量注释: 二、批量取消注…...
Centos7.9 安装Elasticsearch 8.15.1(图文教程)
本章教程,主要记录在Centos7.9 安装Elasticsearch 8.15.1的整个安装过程。 一、下载安装包 下载地址: https://www.elastic.co/cn/downloads/past-releases/elasticsearch-8-15-1 你可以通过手动下载然后上传到服务器,也可以直接使用在线下载的方式。 wget https://artifacts…...
哈希表-数据结构
一、哈希表基本概念 哈希表(也称为散列表)是根据键而直接访问在内存存储位置的数据结构,也就是说实际上是经过哈希函数进行映射,映射道表中一个位置来访问记录,这个存放记录的数组称为散列表。 哈希函数:就…...
指针之旅(4)—— 指针与函数:函数指针、转移表、回调函数
目录 1. 函数名的理解 1.1 “函数名”和“&函数名”的含义 1.2 函数(名)的数据类型 2. 函数指针(变量) 2.1 函数指针(变量)的创建格式 2.2 函数指针(变量)的使用格式 2.3 例子 判别 3. typedef 关键字 3.1 typedef的作用 3.2 typedef的运作逻辑 和 函数指针类型…...
打造线上+线下相结合的O2O平台预约上门服务小程序源码系统 带完整的安装代码包以及搭建部署教程
系统概述 本系统采用前后端分离的设计架构,前端以微信小程序为载体,提供直观、易用的用户界面;后端则采用稳定的服务器架构,确保数据处理的高效与安全。系统主要包括用户端、商户端和管理员端三大模块,通过API接口实现…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
DAY 45 超大力王爱学Python
来自超大力王的友情提示:在用tensordoard的时候一定一定要用绝对位置,例如:tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾: tensorboard的发展历史和原理tens…...
