0


Flink中的时间语义和TTL

时间语义

事件时间(Event Time)

事件时间是数据生成的时间,是数据流中每个元素或者每个事件自带的时间属性,一般是事件发生的时间,在实际项目中作为前端的一个属性嵌入。在理想情况下,数据应当按照事件时间顺序到达集群节点,但是由于从产生一条数据到数据抵达集群有过多的中间步骤,一个较早发生的事件可能较晚到达,使用事件时间意味着会产生数据乱序。

处理时间(Processing Time)

处理时间执行处理操作的机器的系统时间,使用处理时间不需要依赖水位线,也无需缓存,实现也十分简单,是延迟最小的一种时间语义。

注入时间(Ingestion Time)

注入时间是数据进入 Source 算子的时间,任何一个算子的处理速度快慢可能影响到下游算子的处理时间,但是注入时间仅依赖于数据进入 Source 算子的时间,因此不会受制于不同算子的计算时间。

水位线和事件时间

水位线的物理意义有两点:

  1. 水位线本质是一个基于数据生成的、单调递增的时间戳;
  2. 水位线 W(t)表示当前数据流中的所有 t 时刻前的数据都已经到了。

水位线的传播

在实际计算过程中,Flink 的算子一般分布在多个并行的分区(或者称为实例)上,Flink 需要将 Watermark 在并行环境下向前传播。如下图所示,由于上游各分区的处理速度不同,到达当前算子的 Watermark 也会有先后快慢之分,每个算子子任务会维护来自上游不同分区的 Watermark 信息,这是一个列表,列表内对应上游算子各分区的 Watermark 时间戳等信息。每当一个上游传递过来一个水位线,实例会判断该水位线是否大于列表中记录的数值,如果大于则更新水位线。接着实例会遍历整个水位线列表找出最小值作为实例的事件时间,最后,实例会将更新的 Event Time 作为 Watermark 发送给下游所有算子子任务。

时间事件的提取和水位线的生成

周期性的生成水位线,默认周期是 200 毫秒。可以使用

ExecutionConfig.setAutoWatermarkInterval()

方法进行设置。

我们也可以使用

assignTimestampsAndWatermarks()

来分配时间戳和水位线。该方法主要依赖于 WatermarkStrategy 接口,通过 WatermarkStrategy 我们可以为每个元素抽取时间戳并生成 Watermark。基本的使用方法如下:

DataStream.assignTimestampsAndWatermarks(WatermarkStrategy  
        .<Event>forBoundedOutOfOrderness(Duration.ZERO)  
        .withTimestampAssigner((SerializableTimestampAssigner<Event>)  
                (element, recordTimestamp) -> element.timeStamp))
forGenerator ()

方法用来生成 Watermark,本质是返回了一个 WatermarkGenerator有俩种实现机制

BoundedOutOfOrdernessWatermarks(数据存在乱序的情况)

AscendingTimestampsWatermark(数据有序)
withTimestampAssigner ()

方法用来为数据流的每个元素设置时间戳

TTL

public void open(Configuration parameters) throws Exception {
        // 创建MapState描述符
        MapStateDescriptor<String, Long> descriptor = new MapStateDescriptor<>("myMapState", String.class, Long.class);
        StateTtlConfig ttlConfig = StateTtlConfig
                // 状态有效时间
                .newBuilder(Time.seconds(10))
                //设置状态更新类型
                .setUpdateType(StateTtlConfig.UpdateType.OnReadAndWrite)
                // 已过期但还未被清理掉的状态如何处理
                .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
                // 过期对象的清理策略
                .cleanupFullSnapshot()
                .build();
        descriptor.enableTimeToLive(ttlConfig);
        mapState = getRuntimeContext().getMapState(descriptor);
    }

配置分析

设置状态更新类型

setUpdateType(StateTtlConfig.UpdateType.OnReadAndWrite):

在读和写的时候更新过期时间

setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite):

只在创建和写的时候更新过期时间 (默认)

已过期但还未被清理掉的状态如何处理

setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)

不返回过期值

setStateVisibility(StateTtlConfig.StateVisibility.ReturnExpiredIfNotCleanedUp)

可以返回过期值

过期转态的清理策略

⭐ lazy 删除策略:就是在访问 State 的时候根据时间戳判断是否过期,如果过期则主动删除 State 数据

⭐ full snapshot cleanup 删除策略:从状态恢复(checkpoint、savepoint)的时候采取做过期删除,但是不支持 rocksdb 增量 ck

⭐ incremental cleanup 删除策略:访问 state 的时候,主动去遍历一些 state 数据判断是否过期,如果过期则主动删除 State 数据

⭐ rocksdb compaction cleanup 删除策略:rockdb 做 compaction 的时候遍历进行删除。仅仅支持 rocksdb

标签: flink java 大数据

本文转载自: https://blog.csdn.net/qq_42456324/article/details/135924989
版权归原作者 大大大大肉包 所有, 如有侵权,请联系我们删除。

“Flink中的时间语义和TTL”的评论:

还没有评论