flink watermark 生成机制与总结

【Flink】深入解析水位线(Watermark)的生成与传递机制 本文深入解析了Apache Flink中水位线(Watermark)的核心机制。作为事件时间处理的基石,水位线通过平衡延迟与准确性,解决了乱序流处理中窗口触发的难题。文章详细阐述了水位线的生成策略、在分布式任务间的传递逻辑,并提供了处理迟到数据的实用方法,是构建健壮实时数据管道的必备知识。 阅读详情

watermark 介绍

本质上watermark是flink为了处理eventTime窗口计算提出的一种机制,本质上也是一种时间戳,由flink souce或者自定义的watermark生成器按照需求定期或者按条件生成一种系统event,与普通数据流event一样流转到对应的下游operations,接收到watermark数据的operator以此不断调整自己管理的window event time clock。

首先,eventTime计算意味着flink必须有一个地方用于抽取每条消息中自带的时间戳,所以TimestampAssigner的实现类都要具体实现
long (T element, long previousElementTimestamp);方法用来抽取当前元素的eventTime,这个eventTime会用来决定元素落到下游的哪个或者哪几个window中进行计算。

其次,在数据进入window前,需要有一个Watermarker生成当前的event time对应的水位线,flink支持两种后置的Watermarker:Periodic和Punctuated,一种是定期产生watermark(即使没有消息产生),一种是在满足特定情况的前提下触发。两种Watermark分别需要实现接口为
Watermark getCurrentWatermark()和Watermark checkAndGetNextWatermark(T lastElement, long extractedTimestamp);

如果一个下游算子实例消费者多个上游算子实例,则选择上游最小的watermark作为自己的watermark发往下游,这也是为什么要对齐在这里插入图片描述
另外
在这里插入图片描述

watermark生成方式

在 Flink 中,数据处理中需要通过调⽤ DataStream 中的 assignTimestampsAndWatermarks ⽅法来分配时间和⽔印,该⽅法可以传⼊两种参数,⼀个是 AssignerWithPeriodicWatermarks(周期性生成watermark),另⼀个是 AssignerWithPunctuatedWatermarks(已过期,按指定标记性事件生成 watermark),通常建议在数据源(source)之后就进⾏⽣成⽔印,或者做些简单操作⽐如 filter/map/flatMap 之 后再⽣成⽔印,越早⽣成⽔印的效果会更好,也可以直接在数据源头就做⽣成⽔印。

  • With Periodic Watermarks(常用):周期性(一定时间间隔或者达到一定的记录条数)生成watermark

    • 需要实现AssignerWithPeriodicWatermarks接口
    • 默认周期是200ms,可通过env.getConfig.setAutoWatermarkInterval进行修改
    • 实际生产环境用得多,但必须结合时间或者累计条数两个维度,否则在极端情况下会有很大的延时
  • With Punctuated Watermarks(不常用):在满足自定义条件时生成watermark,每一个元素都有机会判断是否生成一个watermark。

    • 需要实现AssignerWithPunctuatedWatermarks接口
    • 在TPS很高的生产环境下会产生大量的 Watermark,可能在一定程度上对下游算子造成一定的压力,只有在实时性很高的场景才会选择这种方式来进行生成水印
    • 新版 Flink 源码中已经标记为 @Deprecated

watermark 的生成值算法策略

  • 紧跟最大事件时间的 watermark 生成策略(完全不容忍乱序)
    WatermarkStrategy.forMonotonousTimestamps();
  • 允许乱序的 watermark 生成策略(最大事件时间-容错时间)
    WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10)); // 根据实际数据的最大乱序情况来设置
  • 自定义 watermark 生成策略
    WatermarkStrategy.forGenerator(new WatermarkGenerator(){ … } );

watermark策略设置代码


import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import java.time.Duration;

public class sinkFunction {
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource<String> stream = env.socketTextStream("local", 9999);
        stream.assignTimestampsAndWatermarks(WatermarkStrategy.noWatermarks()); //禁用时间时间的推进机制
        stream.assignTimestampsAndWatermarks(WatermarkStrategy.forMonotonousTimestamps()); //紧跟最大时间时间
        stream.assignTimestampsAndWatermarks(WatermarkStrategy.forGenerator()); //自定义watermark生成算法
        stream.assignTimestampsAndWatermarks(WatermarkStrategy.<String>forBoundedOutOfOrderness(Duration.ofSeconds(10))
                .withTimestampAssigner(new SerializableTimestampAssigner<String>() {
                    @Override
                    public long extractTimestamp(String s, long l) {
                        return Long.parseLong(s.split(",")[0]);
                    }
                }));
        
    }
}

watermark源码分析

背景代码: source.map(s->bean).assignWatermarkAndTimestamps( ).process().print();

watermark源码调用流程debug(重要)

想要知道代码是如何调用的,我们通过debug的方式来查看数据调用:
我们测试的代码是这样的:

package Launcher;


import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import java.time.Duration;
//nc -lk 9999
public class sinkFunction {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource<String> stream = env.socketTextStream("localhost", 9999);
//        stream.assignTimestampsAndWatermarks(WatermarkStrategy.noWatermarks()); //禁用时间时间的推进机制
//        stream.assignTimestampsAndWatermarks(WatermarkStrategy.forMonotonousTimestamps()); //紧跟最大时间时间
//        stream.assignTimestampsAndWatermarks(WatermarkStrategy.forGenerator()); //自定义watermark生成算法
        stream.assignTimestampsAndWatermarks(WatermarkStrategy.<String>forBoundedOutOfOrderness(Duration.ofSeconds(10))
                .withTimestampAssigner(new SerializableTimestampAssigner<String>() {
                    @Override
                    public long extractTimestamp(String s, long l) {
                        return Long.parseLong(s.split(",")[0]);
                    }
                }));
        stream.print();
        env.execute();

    }
}

代码很简单,什么都没有,就一个设置watermark
我们先打了两个断点在源码的BoundedOutOfOrdernessWatermarks.class中:
在这里插入图片描述

然后开启nc窗口:
在这里插入图片描述

当我们debug后,没有任何输入就会在output.emitWatermark(new Watermark(this.maxTimestamp - this.outOfOrdernessMillis - 1L));处 断点停止,因为这个函数是有定时器触发的,只要程序跑起来,每200ms就会触发一次:
在这里插入图片描述

这个两百是怎么来的呢?点这里可以看到:
在这里插入图片描述
这是task类封装的,一个底层算子类TimestampsAndWatermarksOperator,看这个类的open方法中的这里:
在这里插入图片描述
这里注册了一个计时器,时间是当前时间加watermarkInterval 后触发,这个watermarkInterval 就是200ms。

在这里插入图片描述而触发方法,这里在调用了watermarkGenerator.onPeriodicEmit,并且有重新注册了一个200ms后的定时,实现了 每隔200ms触发一次的效果。

如果想修改源码,看一些效果,可以完全按照源码的包名,类名,写一个一模一样的java类,类加载器会优先加载自己写的代码,而不会去加载引入的源码中代码。

在这里插入图片描述
这里可以看到,数据来了,他是先数据 collect,后触发水印的onevent方法,也就是后更新watermark值。

测试思路

构造两条单并行度流,合并成一个单并行度流,来 watermark,及重点观察“接收多个上游分区”的 算子的 watermark 推进规律;
在这里插入图片描述

/**
 * 作者:深海 "deep as the sea"
 * 日期:2022/4/10
 * 联系方式:qq:657270652 wx:doitedu2018
 * 网站:多易教育 www.51doit.cn
 * 描述:watermark 推进测试观察
 **/
public class WatermarkTest {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        // 构造一个无乱序延迟的 watermark 生成策略
        WatermarkStrategy<String> stringWatermarkStrategy = WatermarkStrategy.<String>forMonotonousTimestamps()
                .withTimestampAssigner(new SerializableTimestampAssigner<String>() {
                    @Override
                    public long extractTimestamp(String element, long recordTimestamp) {
                        return Long.parseLong(element.split(",")[1]);
                    }
                });

        // 构造单并行度流 1
        DataStreamSource<String> source1 = env.socketTextStream("localhost", 9988);
        SingleOutputStreamOperator<String> s1 = source1.assignTimestampsAndWatermarks(stringWatermarkStrategy);

        // 构造单并行度流 2
        DataStreamSource<String> source2 = env.socketTextStream("localhost", 9999);
        SingleOutputStreamOperator<String> s2 = source2.assignTimestampsAndWatermarks(stringWatermarkStrategy);

        // 两条单并行度流,合并到一条单并行度流
        DataStream<String> s = s1.union(s2);

        // 打印 watermark 信息,观察 watermark 推进情况
        s.process(new ProcessFunction<String, String>() {
            @Override
            public void processElement(String value, Context ctx, Collector<String> out) throws Exception {
                // 获取当前的 watermark(注意:此处所谓当前 watermark 是指处理当前数据前的 watermark)
                long currentWatermark = ctx.timerService().currentWatermark();
                Long timestamp = ctx.timestamp();
                System.out.println("s" + " : " + timestamp + " : " + currentWatermark + " => " + value);
                out.collect(value);
            }
        }).print();

        env.execute();
    }
}

测试结果

在 9988 端口输入数据: a,1000
在 9999 端口输入数据: b,1000 b,4000 b,5000
输出结果:
s: 1000 : -9223372036854775808 => a,1000
s: 1000 : -9223372036854775808 => b,1000
s: 4000 : 999 => b,4000
s: 5000 : 999 => b,5000

迟到时间处理

  • 直接丢弃:将迟到事件视为错误消息并丢弃(flink默认处理方式)。
  • Side Output机制:可以将迟到事件单独放入一个数据流分支,这会作为 window 计算结果的副产品,以便用户获取并对其进行特殊处理。
  • Allowed Lateness机制:允许用户设置一个允许的最大迟到时长。Flink 会再窗口关闭后一直保存窗口的状态直至超过允许迟到时长,这期间的迟到事件不会被丢弃,而是默认会触发窗口重新计算。因为保存窗口状态需要额外内存,并且如果窗口计算使用了 ProcessWindowFunction API 还可能使得每个迟到事件触发一次窗口的全量计算,代价比较大,所以允许迟到时长不宜设得太长,迟到事件也不宜过多,否则应该考虑降低水位线提高的速度或者调整算法。

FlinkSql 中的watermark

在创建表的 DDL 中定义
事件时间属性可以用 WATERMARK 语句在 CREATE TABLE DDL 中进行定义。WATERMARK 语句在一个已有字段上定义一个 Watermark 生成表达式,同时标记这个已有字段为时间属性字段。

CREATE TABLE user_actions (
user_name STRING,
 data STRING,
user_action_time TIMESTAMP(3),
 -- 声明 user_action_time 是事件时间属性,并且用 延迟 5 秒的策略来生成 watermark
WATERMARK FOR user_action_time AS user_action_time - INTERVAL '5' SECOND
) WITH (
...
);

SELECT TUMBLE_START(user_action_time, INTERVAL '10' MINUTE), COUNT(DISTINCT user_name)
FROM user_actions
GROUP BY TUMBLE(user_action_time, INTERVAL '10' MINUTE);

如果源中的时间戳数据表示为一个 epoch time,通常是一个长值,例如 1618989564564,建议将事件时间属性定义为 TIMESTAMP_LTZ 列

CREATE TABLE user_actions (
user_name STRING,
 data STRING,
ts BIGINT,
time_ltz AS TO_TIMESTAMP_LTZ(ts, 3),
 -- declare time_ltz as event time attribute and use 5 seconds delayed watermark strategy
WATERMARK FOR time_ltz AS time_ltz - INTERVAL '5' SECOND
) WITH (
...
);

SELECT TUMBLE_START(time_ltz, INTERVAL '10' MINUTE), COUNT(DISTINCT user_name)
FROM user_actions
GROUP BY TUMBLE(time_ltz, INTERVAL '10' MINUTE);

引出问题与源码分析

我们这里来引出一个问题,不能排除有同学就是想用ProcessTime。

那么问题来了,EventTime 情况的watermark 很好理解,
可是ProcessTime的watermark到底做了什么,也不需要用它来过滤数据,本来就没有用数据内的时间,根本就不知道数据的顺序,更谈不上乱序了,那ProcessTime起了什么用呢?

我们首先来看下env.setStreamTimeCharacteristic() 这个方法

/**
    * Sets the time characteristic for all streams create from this environment, e.g., processing
    * time, event time, or ingestion time.
    *
    * <p>If you set the characteristic to IngestionTime of EventTime this will set a default
    * watermark update interval of 200 ms. If this is not applicable for your application
    * you should change it using {@link ExecutionConfig#setAutoWatermarkInterval(long)}.
    *
    * @param characteristic The time characteristic.
    */
   @PublicEvolving
   public void setStreamTimeCharacteristic(TimeCharacteristic characteristic) {
   	this.timeCharacteristic = Preconditions.checkNotNull(characteristic);
   	if (characteristic == TimeCharacteristic.ProcessingTime) {
   		getConfig().setAutoWatermarkInterval(0);
   	} else {
   		getConfig().setAutoWatermarkInterval(200);
   	}
   }

这个方法设置用户使用的是eventtime还是processtime

由源码可以看到 ,如果设置的是ProcessingTime ,会把autoWatermarkInterval这个属性值设为0,如果是EventTime,会设置为 200,我们追踪这个值发现,用户自定义的watermark类,需要注册在assignTimestampsAndWatermarks中,而在assignTimestampsAndWatermarks类中能够找到TimestampsAndPeriodicWatermarksOperator,
TimestampsAndPeriodicWatermarksOperator的open方法中有autoWatermarkInterval这个属性值。

public SingleOutputStreamOperator<T> assignTimestampsAndWatermarks(
			AssignerWithPeriodicWatermarks<T> timestampAndWatermarkAssigner) {
 
		// match parallelism to input, otherwise dop=1 sources could lead to some strange
		// behaviour: the watermark will creep along very slowly because the elements
		// from the source go to each extraction operator round robin.
		final int inputParallelism = getTransformation().getParallelism();
		final AssignerWithPeriodicWatermarks<T> cleanedAssigner = clean(timestampAndWatermarkAssigner);
 
		TimestampsAndPeriodicWatermarksOperator<T> operator =
				new TimestampsAndPeriodicWatermarksOperator<>(cleanedAssigner);
 
		return transform("Timestamps/Watermarks", getTransformation().getOutputType(), operator)
				.setParallelism(inputParallelism);
	}

@Override
	public void open() throws Exception {
		super.open();
 
		currentWatermark = Long.MIN_VALUE;
		watermarkInterval = getExecutionConfig().getAutoWatermarkInterval();
 
		if (watermarkInterval > 0) {
			long now = getProcessingTimeService().getCurrentProcessingTime();
			getProcessingTimeService().registerTimer(now + watermarkInterval, this);
		}
	}

我们来看这个open的初始方法,这个open是TimestampsAndPeriodicWatermarksOperator的初始方法,其实也是assignTimestampsAndWatermarks启动的条件,这个open给定了watermark的初始值。

这里初始化了两个值,

  • 一个是其实的watermark的初始值,最小的long值,-9223372036854775808
  • 另一个是初始的 watermark的间隔 如果是 EventTime就是当前时间加200ms,如果是ProcessTime就是当前时间。

再来看下面的定时任务

	@Override
	public void onProcessingTime(long timestamp) throws Exception {
		// register next timer
		Watermark newWatermark = userFunction.getCurrentWatermark();
		if (newWatermark != null && newWatermark.getTimestamp() > currentWatermark) {
			currentWatermark = newWatermark.getTimestamp();
			// emit watermark
			output.emitWatermark(newWatermark);
		}
 
		long now = getProcessingTimeService().getCurrentProcessingTime();
		getProcessingTimeService().registerTimer(now + watermarkInterval, this);
	}

再来看下我们自定义注册的watermark方法

     @Override
     public Watermark getCurrentWatermark() {
         // return the watermark as current highest timestamp minus the out-of-orderness bound
         return new Watermark(currentMaxTimestamp - maxOutOfOrderness);
     }

autoWatermarkInterval为0的话 super.open() 不会被调用

这里面now,就是System.currentTimeMillis(); 所以如果时间间隔不为0,那么下一次调用的时间就是 当前时间 + 方法运行的时间 + 时间间隔,由于方法运行的时间约等于0ms,所以基本就是每个时间间隔(默认200ms),运行一次获取wakermark的方法。

所以如果是ProcessingTime,那么默认时间间隔是0,所以matermarks时间就是一直-9223372036854775808,所以就一直不会过滤时间。
所以想要启动ProcessingTime 来做 时间戳 ,就一定要设置
env.getConfig().setAutoWatermarkInterval(200);

Flink---WaterMark机制 背景  使用Event time时间模型时,由于网络或传输等原因,事件被Flink处理的顺序不一定是事件产生的顺序(乱序),可能会存在两方面影响: 当前窗口不知道何时停止,开始计算结果; 影响窗口计算结果的准确性,见示例; WaterMark机制  WaterMark本质上是一个带有时间戳的特殊event,当Flink中的运算符接收到水印时,它明白(假设)它不会看到比该时间戳更早的消息。  ... 阅读详情

相关推荐

Flink源码解析:watermark生成与传递

watermark生成 watermark的生成策略有两种:一种是周期性生成,另外一种是根据特定标记生成。在实际使用中大多数情况下会选择周期性生成方式也就是AssignerWithPeriodicWatermarks方式,使用方式如下: // An highlighted block //指定为evenTime时间语义 env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) //生成watermark的周期 env.getConfig.se

jon_snow666的博客 1750

Flink watermark 机制详解

Flink 的 Watermark 机制是实现事件时间处理(Event Time Processing)和窗口操作的关键组成部分。它用于协调流式数据中的事件时间和处理时间,并确保窗口操作的正确性。

kankan_s的专栏 506

flink watermark原理总结

flink watermark学习总结 flink如何处理乱序? 通过窗口对input按照eventTime进行聚合,使得大体按照event time 发生的顺序去处理数据,同时利用watermark来触发窗口。(watermark + window机制) watermark原理及简介? Watermark是Flink为了处理EventTime时间类型的窗口计算提出的一种机制,本质上也是一种时间戳...

The_Inertia的博客 1108

Flink Sql 中 Watermark 使用方式

1、创建 env 和 tableEnv 环境 2、利用 Sql 定义 Source 数据源(并在数据源中定义Watermark和event-time),连接Source 3、利用滑动窗口Hop测试Watermark和event-time是否定义成功 4、利用Window TopN实现业务逻辑 val env = StreamExecutionEnvironment.getExecutionEnvironment env.setParallelism(1) val sett

Y_FC_EMBEDD的博客 6198

Flink Watermark机制

flink watermark详解

chanyue123的博客 2296

空0013

13。

Direction_Wind的博客 2195

Flink1.11 intervalJoin watermark生成,状态清理机制源码理解&Demo分析

参考博客https://cloud.tencent.com/developer/article/1738836 数据类型为左流FlinkClick(userid=gk01, click=Pay, ctime=2020-12-14 09:55:00.000) ; 右流为FlinkPay(userid=gk01, payway=alipy, ptime=2020-12-14 09:58:00.000) join的这段代码如下 clickOut.keyBy(t->t.getUs...

qq_34864753的博客 2751

FlinkSQL 水印(Watermark)的使用和编程实例

在事件流处理中,我们通常需要根据事件的发生时间进行计算和分析,而事件的发生时间并不总是与事件到达处理系统的时间一致。由于网络传输延迟、数据乱序等原因,事件的到达顺序和事件的实际发生顺序可能存在差异。为了解决这个问题,Flink 引入了水印的概念。水印是一种特殊的事件,它带有一个时间戳,并用于表示在该时间戳之前的事件已经全部到达。换句话说,水印标识了事件时间轴上的一个时间点,该时间点之前的事件都已经到达。水印的引入可以帮助我们处理乱序事件、处理延迟数据以及触发窗口计算等操作。

PixelLancer的博客 888

Flink watermark自定义生成机制

周期性生成Watermark import Source.WaterSensor import org.apache.flink.streaming.api.TimeCharacteristic import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks import org.apache.flink.streaming.api.scala._ import org.apache.flink.streaming

菜鸟也学大数据的博客 859

Ultrascale/Ultrascale+ FPGA GTH IP及结构详解(一)

FPGA GTH Transceiver

houzi6320的博客 1万+

Wordpress实战之第二章安装wordpress 软件需要的软件

使用下载并安装phpstudy面版工具 wget -O install.sh?https://notdocker.xp.cn/install.sh?&& sudo bash install.sh 2.安装成功如下 ==============运行状态========================= webpanel stop phpstudy running =================...

安全参透之旅 612

1.22.FLINK Watermark\Flink窗口(Window)\watermark有什么用?\如何使用Watermarks处理乱序的数据流?\机制及实例详解\生成方式\代码实例

1.22.揭开Watermark的神秘面纱 1.22.1.问题导读 1.22.2.流数据异常该怎么办: 1.22.2.1.Flink窗口(Window) 1.22.2.2.事件时间 1.22.3.watermark有什么用? 1.22.4.如何使用Watermarks处理乱序的数据流? 1.23.Watermark机制及实例详解 1.24.Watermark生成方式 1.25.Watermark代码实例 1.26.Watermark的案例以下转自:https://www.aboutyun.com/threa

涂作权的博客 638

Android System Slice应用加载分析,及启用Slice后,锁屏日期第一次开机正常显示,但后面锁屏不显示问题分析

最近发现Android P上锁屏界面,日期不显示,发现从P开始后,出现了Slice来允许应用以模块化,可交互的方式,插入多个使用场景。Android P的system UI 也使用到了这一特性,表现为锁屏时间,日期,勿扰图标,闹钟等。 如何使用Slice 以System UI中KeyguardSliceView.java来说明它的使用方法 首先,我们打开System UI 的mk 文件,可以看到以...

qq_33595823的博客 3035

别只调延迟时间了!深入理解Flink Watermark的生成与传播机制

本文深入解析Flink Watermark机制,从原理到实战优化全面讲解。通过分析事件时间处理的挑战,详细介绍了Watermark的生成算法、传播机制及生产环境优化策略,特别是与Kafka集成的延迟数据处理实践。文章还提供了疑难问题排查指南和高级应用场景,帮助开发者更好地理解和应用Flink Watermark技术。

weixin_30667831的博客 284

UG\NX二次开发 判断对象是虚线还是实线

网友提问“怎么区分虚线实线”,这个可以通过函数判断。

王牌飞行员_里海的博客 357

从零实战:模拟Soul/陌陌附近的人接口爬虫(设备指纹·加密逆向·动态代理全解)

在移动互联网流量见顶的今天,LBS(基于位置的服务)社交平台——尤其是Soul和陌陌——依然掌握着海量高活用户的地理位置画像、兴趣标签、在线活跃时段等敏感数据。对于市场调研、流量运营、甚至是城市热力分析而言,“附近的人”接口是一个极具价值的入口。然而,这两款App均采用全参数加密 + 设备指纹风控 + WAF动态防御的三重护城河。直接使用Requests库调用公开API无异于以卵击石。本文将从逆向工程视角出发,完整还原一套可用的附近人信息采集方案,涵盖:抓包与流量分析(绕过SSL Pinning)

2201_76125261的博客 211

Flink Time 之 WaterMark 水位线原理剖析:从生成机制到传播触发与调优实战

Flink Watermark水位线原理深度剖析,详解Watermark本质与核心作用、两种生成方式(周期性/断点式)、WatermarkGenerator接口(onEvent/onPeriodicEmit)、内置生成策略(有界乱序/单调递增)、自定义Watermark完整Java代码实现,深入剖析Watermark传播与窗口触发机制、多并行度合并取最小值、空闲输入withIdleness处理,附关键监控指标、八条调优建议与六大常见坑解决方案。

https://starzy1990.github.io/ 481

matlab 受约束的 Delaunay 三角剖分【2025最新版】

matlab内置调用函数实现受约束的 Delaunay 三角剖分并将结果保存为STL文件

点云侠的博客 1875

Flink的Watermark机制:理解与优化

1.背景介绍 Flink的Watermark机制是一种用于处理时间相关数据的机制,它在流处理系统中起着非常重要的作用。在这篇文章中,我们将深入探讨Flink的Watermark机制,涵盖其核心概念、算法原理、具体操作步骤、数学模型公式、代码实例以及未来发展趋势与挑战。 1.1 Flink的流处理系统 Flink是一个用于大规模数据流处理的开源框架,它支持实时数据流处理和批处理 job。Fli...

AI天才研究院 1187

9、硬件工程师笔试面试知识器件篇——三极管(2025版本)

本文全面介绍了三极管的基础知识与应用,包括其结构、类型、工作原理、工作状态、功能、应用场景及特性参数。详细探讨了三极管在信号放大、无线通信、音频设备及医疗设备中的具体应用,并深入分析了设计放大电路时如何平衡增益与噪声、优化偏置电路以提高稳定性、使用负反馈改善性能等关键问题。此外,文章还涵盖了高频电路设计、温度补偿策略、电磁干扰防护等实用内容,为硬件工程师提供了全面的技术参考和设计指导。

XU157303764的博客 7312

Qt C++ 串口调试助手

1. **串口配置**:支持自动检测可用串口,可配置波特率(9600~921600)、数据位(5~8)、校验位(无/奇/偶/标记/空格)、停止位(1/1.5/2)。- HEX 模式发送时,输入格式需为十六进制字符(0-9、A-F),可带空格(如 `01 A3 FF`)或不带空格(如 `01A3FF`)。// 发送模式:true=HEX,false=ASCII。// 字符串转HEX字节数组。ui->parity->addItems({"无", "奇校验", "偶校验", "标记校验", "空格校验"});

寒寒豆豆软件公司的博客 147

Flink的时间类型和watermark机制

Watermark是一个对Event Time的标识,内容方面Watermark是个时间戳,一个带有时间戳X的Watermark到达,相当于告诉Flink系统,Processing Time并不能保证确定性,它容易受到Event到达系统的速度(例如来自消息队列)以及数据在Flink系统内部处理的先后顺序的影响,首先如果这种事情出现的概率非常小,不影响所要求的准确度,除了把违反watermark机制的数据丢弃,也有不丢弃的处理方法,比如通过一些机制来更新之前统计的结果,这种方式会有一定的性能开销。

默硕的博客 497

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Flink Watermark原理与实战

Watermark(水位线)是 Flink 中用于处理事件时间(Event Time)的一种机制 ,它本质上是一种特殊的时间戳。简单来说,Watermark 是插入到数据流中的一个标记,用于标记事件时间的上界。在 Flink 的流处理中,Watermark 可以看作是一个时间戳,它表示所有小于该时间戳的事件都已经到达,之后不会再有该时间戳之前的事件到来。​比如,我们有一个订单流,每个订单都有一个下单时间(事件时间)。

m0_71836706的博客 928

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

深入Flink系列——watermark使用与源码详解

本节我们主要关注Flink的时间体系,包括Flink的时间语义、watermark机制及watermark的生成与传播原理,主要进行一些flink watermark理论知识的梳理。

PAN_Andy的博客 819

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Flink流计算编程--watermark(水位线)简介

1、watermark的概念watermark是一种衡量Event Time进展的机制,它是数据本身的一个隐藏属性。通常基于Event Time的数据,自身都包含一个timestamp,例如1472693399700(2016-09-01 09:29:59.700),而这条数据的watermark时间则可能是:watermark(1472693399700) = 1472693396700(2016

lmalds的专栏 6万+

Flink:watermark

三种时间概念 在谈watermark之前,首先需要了解flink的三种时间概念。在flink中,有三种时间戳概念:Event Time 、Processing Time 和 Ingestion Time。其中watermark只对Event Time类型的时间戳有用。这三种时间概念分别表示: Processing time 处理时间,指执行算子操作的机器的当前时间。当基于处理时间运行时,所有关于时间的操作(如时间窗口)都将使用执行算子操作的机器的本地时间。例如,当时间窗口为一小时时,如果应用程序在9:

啥也不会的博客 4884
上一篇: calcite在flink中的二次开发,介绍解析器与优化器
下一篇: flink内存管理,设置思路,oom问题,一文全
Direction_Wind
博客等级 码龄8年 6438粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Direction_Wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值