【深入浅出flink】第13篇:从源码解读flink中Watermark的周期性和间断式生成方式

本文是《深入浅出Flink》系列的第13篇,详细介绍了Flink中Watermark的生成方式,包括AssignerWithPeriodicWatermarks(周期性)和AssignerWithPunctuatedWatermarks(间断式)。文中通过具体实例讲解了如何自定义这两种Watermark的时间戳分配器,并对比了它们在不同数据量情况下的适用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好,我是雷恩Layne,这是《深入浅出flink》系列的第十三篇文章,希望能对您有所收获O(∩_∩)O


我们通常通过DataStream的assignTimestampsAndWatermarks方法引入Watermark,assignTimestampsAndWatermarks方法中要求传入的接口有两种:

  • AssignerWithPeriodicWatermarks(周期性生成Watermark的时间戳分配器)
  • AssignerWithPunctuatedWatermarks(间断式生成Watermark的时间戳分配器)

它们都是TimestampAssigner(时间戳分配器)接口的子接口。具体继承关系如下图所示:

TimestampAssigner接口只有一个抽象方法extractTimestamp,这个方法定义了eventTime的提取方式:

public interface TimestampAssigner<T> extends Function {
   
   

    //element:当前被分配的元素
    //previousElementTimestamp:上一个元素的时间戳
    //返回值:最新的时间戳(即当前被分配的元素的时间戳)
	long extractTimestamp(T element, long previousElementTimestamp);
}

AssignerWithPeriodicWatermarks和AssignerWithPunctuatedWatermarks的实现类,除了要实现它们本身的方法,还有实现TimestampAssigner接口中的extractTimestamp方法。

一、AssignerWithPeriodicWatermarks

AssignerWithPeriodicWatermarks接口是周期性生成Watermark的时间戳分配器,我们可以在程序中设置生成Watermark的周期,如下:

env.getConfig().setAutoWatermarkInterval(100);//设置每100ms生成Watermark

AssignerWithPeriodicWatermarks接口中只有一个方法,即getCurrentWatermark,源码如下:

public interface AssignerWithPeriodicWatermarks<T> extends TimestampAssigner<T> {
   
   
	@Nullable
	Watermark getCurrentWatermark();
}

系统周期性的调用getCurrentWatermark()来获取当前的Watermark,它返回的Watermark仅在大于上一次返回的Watermark情况下有效。如果获取的Watermark小于上一次获取的Watermark,则表示当前没有更新的数据到来;如果获取的Watermark是null或者小于上次的Watermark,则表示没有生成新的Watermark。

我们可以自定义类实现AssignerWithPeriodicWatermarks的getCurrentWatermark()方法,Flink也有给我们实现的工具类,有如下三种:

  • BoundedOutOfOrdernessTimestampExtractor
  • AscendingTimestampExtractor
  • IngestionTimeExtractor

1.1 BoundedOutOfOrdernessTimestampExtractor

BoundedOutOfOrdernessTimestampExtractor是处理无序数据的时间戳提取器,初始化是会生成一个Watermark,值为Long.MIN_VALUE当一个数据到来后,根据extractTimestamp获取不断更新当前最大的时间戳currentMaxTimestamp。然后,周期定的调用getCurrentWatermark获取当前最新的Watermark。

具体源码实现如下:

public abstract class BoundedOutOfOrdernessTimestampExtractor<T> implements AssignerWithPeriodicWatermarks<T> {
   
   

	private static final long serialVersionUID = 1L;

	/** The current maximum timestamp seen so far. */
	private long currentMaxTimestamp; //当前最大的时间戳,即已经获取到数据的最大时间戳

	/** The timestamp of the last emitted watermark. */
	private long lastEmittedWatermark = Long.MIN_VALUE;//上一次发出的Watermark,初始为Long.MIN_VALUE

	private final long maxOutOfOrderness;//Watermark的延迟时长

	public BoundedOutOfOrdernessTimestampExtractor(Time maxOutOfOrderness) {
   
   
		if (maxOutOfOrderness.toMilliseconds() < 0) {
   
   
			throw new RuntimeException("Tried to set the maximum allowed " +
				"lateness to " + maxOutOfOrderness + ". This parameter cannot be negative.");
		}
		this.maxOutOfOrderness = maxOutOfOrderness.toMilliseconds();//延迟时长单位是毫秒
        
        //初始化时,还没有数据到来,需要给currentMaxTimestamp赋一个初值。为了使其小于后面到来数据的时间戳,一般给其赋Long.MIN_VALUE。但是我们求getCurrentWatermark()时,是通过currentMaxTimestamp - maxOutOfOrderness计算的,如果初始的current
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

雷恩Layne

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

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

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

打赏作者

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

抵扣说明:

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

余额充值