【flink】状态清理策略(TTL)

flink的keyed state是有有效期(TTL)的,使用和说明在官网描述的篇幅也比较多,对于三种清理策略没有进行横向对比得很清晰。

  • 全量快照清理(FULL_STATE_SCAN_SNAPSHOT)
  • 增量清理(INCREMENTAL_CLEANUP)
  • rocksdb压缩清理(ROCKSDB_COMPACTION_FILTER)

在这里插入图片描述

注意,三种状态清理策略不是互斥的,并不是三选一的问题,一般是全量快照清理配合另两个其中的一个来使用(需要根据不同的state backend),可以看到StateTtlConfig.CleanupStrategies.strategies是一个集合来的。

全量快照清理

只发生在全量checkpoint的时候,把过期的元素过滤掉,以减少远程端checkpoint storage的大小(如hdfs),无论状态后端是hashmap还是rocksdb都支持,官网用了另一种相同意思描述:在 RocksDBStateBackend 的增量 checkpoint 模式下无效(当前hashmap不支持增量checkpoint)

  • 开启方式
    StateTtlConfig ttlConfig = StateTtlConfig .newBuilder(Time.seconds(1))
        .cleanupFullSnapshot()   //只要有这行即可
        .build();
// 只有开启了全量快照清理才会触发transform(过滤)
    private StateSnapshotTransformFactory<?> getSnapshotTransformFactory() {
        if (!ttlConfig.getCleanupStrategies().inFullSnapshot()) {
            return StateSnapshotTransformFactory.noTransform();
        } else {
            return new TtlStateSnapshotTransformer.Factory<>(timeProvider, ttl);
        }
    }   

当进行全量快照是会遍历状态中每个元素(TtlValue),过滤掉那些已经过期的StateSnapshotTransformer#filterOrTransform()该接口有几个实现类:

  1. TtlSerializedValueStateSnapshotTransformer:判断value是否过期,用于rocksdb状态后端
  2. TtlDerializedValueStateSnapshotTransformer:判断value是否过期,用于hashmap状态后端
  3. ListStateSnapshotTransformer:经1,2过期判断后的数据处理,对应hashmap后端的ListState
  4. MapStateSnapshotTransformer:经1,2过期判断后数据处理,对应hashmap后端的MapState
  5. RocksDBListState.StateSnapshotTransformerWrapper:经1,2过期判断后的数据处理,对应rocksdb后端的ListState
  6. RocksDBMapState.StateSnapshotTransformerWrapper:经1,2过期判断后的数据处理,对应rocksdb后端的MapState

ps: rocksdb的MapState(第6个实现)中,当每个key的value过期后,返回的是一个byte[1]字节数组,3,4,5都对应返回了null,为什么??在使用时发现即使设置了ttl,但是过了每个ttl周期后,整个checkpoint size还是缓缓地持续增大,可能是依赖于rocksdb的compact把这些数据清理?

当hashmap状态后端只使用了全量清理策略,在checkpoint界面看到的大小每次都都比较平均,但是堆内存却是持续增加的,所以要结合增量清理策略一起使用
在这里插入图片描述

增量清理

在状态访问、增加、修改、删除时都会触发,主要是为了减少状态后端中的大小,当前仅状态后端为hashmap才支持增量清理

这里的增量有点难理解,实际它的含义是:对于一个keyed stated,状态是按key被分区成若干部分的,每次只取cleanupSize个key的状态(StateEntry)进行清理,对于大状态这是必须的,因为这会增加状态算子处理数据的时间。对于rocksdb,由于提供不了全局的StateEntry访问器,所以它不支持增量清理AbstractRocksDBState.getStateIncrementalVisitor

判断是否满足增量清理:TtlStateFactory.registerTtlIncrementalCleanupCallback
清理逻辑:TtlIncrementalCleanup.runCleanup

启用方式:这玩意在hashmap状态后端中是默认开启的!!!

        public IncrementalCleanupStrategy getIncrementalCleanupStrategy() {
            IncrementalCleanupStrategy defaultStrategy =
                    isCleanupInBackground ? DEFAULT_INCREMENTAL_CLEANUP_STRATEGY : null;
            return (IncrementalCleanupStrategy)
                    strategies.getOrDefault(Strategies.INCREMENTAL_CLEANUP, defaultStrategy);
        }

只要isCleanupInBackground=true,就算没显式调用cleanupIncrementally(),它依然会给你生成一个默认的增量清理策略。所以在上述全量快照清理的启用示例中同时也开启了增量清理。如果需要禁止,需要显式调disableCleanupInBackground()

rocksdb压缩清理

flink 提供的 rocksdb 压缩过滤器(FlinkCompactionFilter)会在压缩时过滤掉已经过期的状态数据,最终调用到C++的nactive方法,减少sst文件的大小。应该与增量/全量checkpoint方式无关。

压缩清理依赖于rocksdb自身的压缩策略,触发时间可能并不像增量清理那样实时,所以本地rocksdb会保留超过了TTL很长时间的过期数据(此时处于L1甚至L2),如果需要及时清理本地过期数据,则需要配置更"积极"的压缩策略。

<think> 首先,用户的问题是关于如何在Flink代码中设置状态TTL(Time To Live)。我需要基于提供的引用内容来回答。 回顾系统级指令: - 所有行内数学表达式必须用$...$,但这里可能没有数学表达式,所以可能不适用。 - 独立公式用$$...$$,但同样,这里可能不需要。 - LaTeX语法正确:确保任何数学表达式的格式正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 用户提供的引用: - [^1]: 来自Flink State TTL 详解,展示了设置TTL的代码示例。 - [^2]: 来自Flink状态TTL机制内容详解,解释了TTL机制。 - [^3]: 来自Flink TTL,另一个代码示例。 - [^4]: 来自Flink状态计算TTL,描述了TTL的应用场景。 用户的问题:"我想查找在Flink代码中设置状态TTL的方法 请问Flink代码中如何设置状态TTL" 所以,我需要解释如何在Flink代码中设置状态TTL。基于引用,设置TTL的步骤如下: 1. 导入必要的类。 2. 创建一个StateDescriptor(如ValueStateDescriptor)。 3. 创建一个StateTtlConfig对象,配置TTL参数。 4. 使用stateDescriptor.enableTimeToLive(ttlConfig)启用TTL。 从[^1]和[^3]中,代码示例类似: - StateTtlConfig.newBuilder(Time.seconds(1))设置TTL时间。 - .setUpdateType(...)设置更新类型(如OnCreateAndWrite)。 - .setStateVisibility(...)设置状态可见性(如NeverReturnExpired)。 - .cleanupFullSnapshot()或其他清理选项。 - 然后build()配置。 - 最后,stateDescriptor.enableTimeToLive(ttlConfig)。 在回答中,我需要结构化: - 逐步解释设置过程。 - 提供代码示例。 - 引用来源。 结构回答: 1. 介绍:简要解释什么是状态TTL(基于[^2])。 2. 设置步骤:分步说明。 3. 代码示例:使用引用中的代码,但可能需要简化或解释。 4. 解释关键配置:如时间单位、更新类型、状态可见性。 5. 生成相关问题。 确保回答在中文。 生成相关问题: - 基于主题,如TTL配置选项、清理策略、应用场景等。 - 参考系统指令的示例:"§§相关问题§§"后列出问题。 添加引用标识: - 在相关部分末尾添加[^1], [^2]等。 最终回答结构: - 回答用户问题。 - 提供清晰的步骤和代码。 - 在末尾添加相关问题。 </think> ### Flink代码中设置状态TTL的方法 在Apache Flink中,状态TTL(Time To Live)是一种自动删除过期状态数据的机制,常用于优化内存使用和防止状态数据累积。设置状态TTL的核心是通过`StateTtlConfig`配置状态描述符(如`ValueStateDescriptor`)。以下是基于官方文档和最佳实践的逐步说明(使用Java API): #### 步骤1: 导入必要的类 首先,导入Flink状态管理相关的类: ```java import org.apache.flink.api.common.state.StateTtlConfig; import org.apache.flink.api.common.state.ValueStateDescriptor; // 或其他状态描述符,如ListStateDescriptor import org.apache.flink.api.common.time.Time; ``` #### 步骤2: 创建状态描述符 定义一个状态描述符,例如`ValueStateDescriptor`,用于存储状态数据的类型和名称: ```java ValueStateDescriptor<Long> stateDescriptor = new ValueStateDescriptor<>( "LastLoginState", // 状态名称 Long.class // 状态数据类型 ); ``` #### 步骤3: 配置TTL参数 使用`StateTtlConfig.newBuilder()`构建TTL配置。关键参数包括: - **TTL时间**:通过`newBuilder(Time.时间单位)`设置过期时间(例如`Time.minutes(1)`表示1分钟后过期)。 - **更新时间类型**:`setUpdateType()`定义何时重置TTL计时器,常用`StateTtlConfig.UpdateType.OnCreateAndWrite`(仅在创建或写入时更新)。 - **状态可见性**:`setStateVisibility()`控制过期数据是否可见,推荐`StateTtlConfig.StateVisibility.NeverReturnExpired`(永不返回过期数据)[^1][^3]。 - **清理策略**:添加清理方法,如`.cleanupFullSnapshot()`(全量快照时清理)或`.cleanupIncrementally()`(增量清理)[^1][^2]。 完整配置示例: ```java StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.minutes(1)) // TTL为1分钟 .setTtlTimeCharacteristic(StateTtlConfig.TtlTimeCharacteristic.ProcessingTime) // 使用处理时间 .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite) // 创建/写入时更新TTL .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired) // 隐藏过期数据 .cleanupFullSnapshot() // 全量快照时清理过期数据 .build(); // 构建配置 ``` #### 步骤4: 启用TTL并应用状态描述符 将TTL配置附加到状态描述符: ```java stateDescriptor.enableTimeToLive(ttlConfig); ``` 然后,在Flink算子(如`RichFlatMapFunction`)中使用该描述符注册状态: ```java public class MyOperator extends RichFlatMapFunction<InputType, OutputType> { private ValueState<Long> state; @Override public void open(Configuration parameters) { state = getRuntimeContext().getState(stateDescriptor); // 启用TTL状态 } @Override public void flatMap(InputType value, Collector<OutputType> out) { // 使用state.value()读取或state.update()写入状态 // 过期数据会自动处理 } } ``` #### 关键说明 - **时间语义**:TTL支持`ProcessingTime`(处理时间)或`EventTime`(事件时间),但需注意Flink 1.11及更早版本主要支持处理时间[^4]。 - **性能影响**:设置过长TTL可能导致状态膨胀,过短则可能误删数据。建议根据业务需求测试优化。 - **清理机制**:除`.cleanupFullSnapshot()`外,还可使用`cleanupInBackground()`进行后台清理以减少开销[^2]。 通过以上步骤,Flink会在状态数据过期后自动删除,适用于会话管理、窗口计算等场景[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值