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

java 复制代码
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

相关推荐
小bo波5 小时前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
大大大大晴天5 小时前
Hudi技术内幕:Key Generation原理与实践
大数据
nanxun8861 天前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103511 天前
Day01 | Java 基础(Java SE)
java
行者全栈架构师1 天前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师2 天前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_02 天前
mac(m5)平台编译openjdk
java
唐青枫3 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马3 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261353 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java