【FLink-14-Flink 状态State的TTL管理&Flink状态后端】

FLink-14-Flink 状态State的TTL管理

  • Flink 状态State的TTL管理
    • 1.updateTtlOnReadAndWrite()/updateTtlOnCreateAndWrite()
    • 2.StateTtlConfig.StateVisibility.NeverReturnExpired/ReturnExpiredIfNotCleanedUp
    • 3.cleanupStrategies(过期数据清理策略,目前支持的策略有)
      • 嵌入式数据库相关整理
      • HBase中的compact机制:major合并和minor合并
  • Flink状态后端
    • 1.Flink状态后端的定义:
    • 2.Flink状态后端的分类
    • 3.Flink状态后端和TTL的具体代码案例如下:

Flink 状态State的TTL管理

  • flink 可以对状态数据进行存活时长管理,即"新陈代谢";
  • 淘汰的机制主要是基于存活时间;
  • 存活时长的计时器可以在数据被读、写时重置;
  • Ttl 存活管理粒度是到元素级的(如 liststate 中的每个元素,mapstate 中的每个 entry),每条数据都有自己独立的TTL计时。
  • 应用场景:
    • 如果维度数据很大,量级很多,
      • 可以将维度数据中热数据存放到State状态中,查询维度数据时,优先从state中查看,没有的话,再从基础架构中查询,这样就缩短了查询维度数据的时长;
      • 同时,state中可以根据自定义需求设置TTL生命管理机制,为状态中数据设置失效时长以及失效策略。

1.updateTtlOnReadAndWrite()/updateTtlOnCreateAndWrite()

  • updateTtlOnReadAndWrite() : ttl 重置刷新策略,数据只要被读取或者被写更新,则将它的 ttl 计时重置.
  • updateTtlOnCreateAndWrite() : ttl 重置刷新策略,数据被创建及被写入更新,就将它的 ttl 计时重置

2.StateTtlConfig.StateVisibility.NeverReturnExpired/ReturnExpiredIfNotCleanedUp

  • NeverReturnExpired(默认策略):状态数据的可见性:如果状态中存在还未清理掉的但是已经超出 ttl 的数据,不允许让用户程序可见,如下图所示
    【FLink-14-Flink 状态State的TTL管理&Flink状态后端】_第1张图片

  • ReturnExpiredIfNotCleanedUp:如果状态中存在还未清理掉的但是已经超出 ttl 的数据,可以允许让用户程序可见。

3.cleanupStrategies(过期数据清理策略,目前支持的策略有)

    1. cleanupIncrementally : 增量清除 每当访问状态时,都会驱动一次过期检查(算子注册了很多 key 的 state,一次检查只针对其中一部分: 由参数 cleanupSize 决定) 算子持有一个包含所有 key 的迭代器,每次检查后,迭代器都会向前 advance 指定的 key 数量; 本策略,针对“本地状态空间”,且只用于 HashMapStateBackend

【FLink-14-Flink 状态State的TTL管理&Flink状态后端】_第2张图片

    1. cleanupFullSnapshot 在进行全量快照(checkpoint)时,清理掉过期数据; 注意:只是在生成的 checkpoint 数据中不包含过期数据;在本地状态空间中,并没有做清理; 本策略,针对“快照”生效
    1. cleanupInRocksdbCompactFilter 只针对 rocksdbStateBackend 有效; 它是利用 rocksdb 的 compact 功能,在 rocksdb 进行 compact 时,清除掉过期数据; 本策略,针对“本地状态空间”,且只用于 EmbeddedRocksDbStateBackend

嵌入式数据库相关整理

  • derby是一个数据库软件,任何软件都可以内嵌此数据库软件,它跟Mysql不同之处在于:
    • mysql是一个独立的软件,是一个服务
    • derby是一个嵌入式的数据库软件(工具包)
    • derby是支持sql的关系型数据库
  • rockdb就是一种嵌入式数据库 ,是kv数据库。

HBase中的compact机制:major合并和minor合并

【FLink-14-Flink 状态State的TTL管理&Flink状态后端】_第3张图片

Flink状态后端

1.Flink状态后端的定义:

  • 所谓状态后端,就是状态数据的存储管理实现,包含状态数据的本地读写、快照远端存储功能;
  • 状态后端是可插拔替换的,它对上层屏蔽了底层的差异,因为在更换状态后端时,用户的代码不 需要做任何更改。

2.Flink状态后端的分类

  • Flink状态后端使用来存储Flink的State状态的,不管是valueState/listState/mapState/aggregateState/reduceingState都存储在状态后端里面,状态后端是放置在heap堆中,如果内存不够就会溢写到本地磁盘,状态后端有两种实现:
    • HashMapStateBackend
      • 默认使用此状态后端,状态数据就是存储在内存中,数据以对象的形式存在,内存不够溢写磁盘。
    • RocksDbStateBackend
      • 使用此状态后端,状态数据就不再是以java对象的形式存在,而是被序列化成字节存储。
      • 存储超大规模的状态数据,用RocksDbStateBackend,综合效率更高。
      • rocksDb中也有类似于HBase的compact的操作,在进行此操作的时候,可以将状态中的数据清理干净。
    • 两种statebackend,生成的快照文件,格式是完全一致的。 这样做的目的:便于重启后,改变statebackend后,还能继续兼容重启前的上一种backend所生成的快照数据。
  • 老版本(flink-1.12 版及以前) Fsstatebackend MemoryStatebackend RocksdbStateBackend
    【FLink-14-Flink 状态State的TTL管理&Flink状态后端】_第4张图片
  • 如需使用 rocksdb-backend,需要引入依赖以及代码中相关使用如下:
1.引入依赖
		<dependency> 
            <groupId>org.apache.flink</groupId> 
            <artifactId>flink-statebackend-rocksdb_2.12</artifactId> 
            <version>${flink.version}</version>
        </dependency>

2.代码中设置参数:
        /**
         * 设置要使用的状态后端
         */
        HashMapStateBackend hashMapStateBackend = new HashMapStateBackend();
        env.setStateBackend(hashMapStateBackend);//使用HashMapStateBackend作为状态后端
        EmbeddedRocksDBStateBackend embeddedRocksDBStateBackend = new EmbeddedRocksDBStateBackend();
        env.setStateBackend(embeddedRocksDBStateBackend);//设置 EmbeddedRocksDBStateBackend 作为状态后端

3.Flink状态后端和TTL的具体代码案例如下:

package com.yang.flink.state;

import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.functions.AggregateFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.api.common.functions.RuntimeContext;
import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.api.common.state.*;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.contrib.streaming.state.EmbeddedRocksDBStateBackend;
import org.apache.flink.runtime.state.hashmap.HashMapStateBackend;
import org.apache.flink.streaming.api.CheckpointingMode;
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.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 键控状态使用演示
 */
public class TTLStateDemo {
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        env.setRuntimeMode(RuntimeExecutionMode.STREAMING);

        /**
         * 设置要使用的状态后端
         */
        HashMapStateBackend hashMapStateBackend = new HashMapStateBackend();
        env.setStateBackend(hashMapStateBackend);//使用HashMapStateBackend作为状态后端
        EmbeddedRocksDBStateBackend embeddedRocksDBStateBackend = new EmbeddedRocksDBStateBackend();
        env.setStateBackend(embeddedRocksDBStateBackend);//设置 EmbeddedRocksDBStateBackend 作为状态后端


        // 开启状态数据的checkpoint机制(快照的周期,快照的模式)
        env.enableCheckpointing(1000, CheckpointingMode.EXACTLY_ONCE);
        // 开启快照后,就需要指定快照数据的持久化存储位置
        env.getCheckpointConfig().setCheckpointStorage("file:///d:/checkpoint/");
        // 开启  task级别故障自动 failover
        env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,1000));
        DataStreamSource<String> source = env.socketTextStream("localhost", 9999);
        // 需要使用map算子来达到一个效果:
        // 每来一条数据(字符串),输出 该条字符串拼接此前到达过的所有字符串
        SingleOutputStreamOperator<String> mapOperator = source.keyBy(s -> s)
                .map(new RichMapFunction<String, String>() {//使用map算子时候,键控状态算子,需要实现rich的function,获取到flink的状态
                    // 单值状态
                    ValueState<String> valueState;
                    // list状态
                    ListState<String> lstState;
                    // map状态
                    MapState<String, String> mapState;
                    @Override
                    public void open(Configuration parameters) throws Exception {
                        RuntimeContext runtimeContext = getRuntimeContext();

                        StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.seconds(5))//配置数据存活时长为5秒
//                                .updateTtlOnCreateAndWrite()//当插入和更新数据的时候,将该条数据的ttl计时重置
//                                .updateTtlOnReadAndWrite()//当读、写数据的时候,将该条数据的ttl计时重置
//                                .setStateVisibility(StateTtlConfig.StateVisibility.ReturnExpiredIfNotCleanedUp)//允许返回已过期但尚未被清理的数据
//                                .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)//不允许返回已过期但尚未被清理的数据
                                .setTtlTimeCharacteristic(StateTtlConfig.TtlTimeCharacteristic.ProcessingTime)//ttl计时的时间语义:设置为processTime
                                .useProcessingTime()//ttl计时的时间语义:设置为processTime
                                .cleanupIncrementally(1000,true)//增量清理(每当一条状态数据被访问,则会检查这条数据的ttl是否超时,是就删除)
                                .cleanupFullSnapshot()//全量快照清理策略(在checkpoint的时候,保存到快照文件中的只包含未过期的状态数据,但是它并不会清理算子本地的状态数据)
                                .cleanupInRocksdbCompactFilter(1000)//在rockdb的compact机制中添加过期数据过滤器,以在compact过程中清理掉过期状态数据
                                .build();


                        ValueStateDescriptor<String> vstate = new ValueStateDescriptor<>("vstate", String.class);
                        vstate.enableTimeToLive(ttlConfig);//开启TTL管理

                        ListStateDescriptor<String> lst = new ListStateDescriptor<>("lst", String.class);
                        lst.enableTimeToLive(ttlConfig);


                        // 获取一个 单值 结构的状态存储器
                        valueState = runtimeContext.getState(vstate);
                        // 获取一个List结构的状态存储器
                        lstState = runtimeContext.getListState(lst);
                        // 获取一个 Map 结构的状态存储器
                        mapState = runtimeContext.getMapState(new MapStateDescriptor<String, String>("xx", String.class, String.class));


                    }

                    @Override
                    public String map(String value) throws Exception {
                        lstState.add(value);

                        StringBuilder sb = new StringBuilder();
                        Iterable<String> iterable = lstState.get();
                        for (String s : iterable) {
                            sb.append(s);
                        }

                        return sb.toString();
                    }
                });
        mapOperator.print();
    }
}

你可能感兴趣的:(大数据,flink,flink,数据库,大数据)