Flink状态State管理、后端存储、Checkpoint

Flink的状态State介绍和应用场景解析

什么是State状态

是一个Operator的运行的状态/历史值,是维护在内存中
数据流处理离不开状态管理,比如窗口聚合统计、去重、排序等
流程:
一个算子的子任务接收输入流,获取对应的状态,计算新的结果,然后把结果更新到状态里面
在这里插入图片描述

有状态和无状态介绍
  • 无状态计算

同个数据进到算子里面多少次,都是一样的输出,比如 filter

  • 有状态计算

需要考虑历史状态,同个输入会有不同的输出,比如sum、reduce聚合操作

状态管理分类
ManagedState(用的多)
Flink管理,自动存储恢复
细分两类:
1.Keyed State 键控状态(用的多)
	a.有KeyBy才用这个,仅限用在KeyStream中,每个key都有state ,是基于KeyedStream上的状态
	b.一般是用richFlatFunction,或者其他richfunction里面,在open()声明周期里面进行初始化
	c.ValueState、ListState、MapState等数据结构
2. Operator State 算子状态(用的少,部分source会用)
	a.ListState、UnionListState、BroadcastState等数据结构
RawState(用的少)
用户自己管理和维护
存储结构:二进制数组
state数据结构

状态值可能存在内存、磁盘、DB或者其他分布式存储中

  • ValueState 简单的存储一个值(ThreadLocal / String)

    ValueState.value()
    ValueState.update(T value)

  • ListState 列表

    ListState.add(T value)
    ListState.get() //得到一个Iterator

  • MapState 映射类型

    MapState.get(key)
    MapState.put(key, value)

State 后端存储

官网链接:https://ci.apache.org/projects/flink/flink-docs-release-1.13/docs/ops/state/state_backends/
State状态后端:存储在哪里
Flink 内置了以下这些开箱即用的 state backends :

  • 新版

HashMapStateBackend、EmbeddedRocksDBStateBackend
如果没有其他配置,系统将使用 HashMapStateBackend。

  • 旧版

MemoryStateBackend、FsStateBackend、RocksDBStateBackend

如果不设置,默认使用 MemoryStateBackend。

状态详解

HashMapStateBackend 保存数据在内部作为Java堆的对象。

  1. 键/值状态和窗口操作符持有哈希表,用于存储值、触发器等
  2. 非常快,因为每个状态访问和更新都对 Java 堆上的对象进行操作
  3. 但是状态大小受集群内可用内存的限制

场景:

  • 具有大状态、长窗口、大键/值状态的作业。
  • 所有高可用性设置。

EmbeddedRocksDBStateBackend 在RocksDB数据库中保存状态数据

  1. 该数据库(默认)存储在 TaskManager 本地数据目录中
  2. 与HashMapStateBackend在java存储 对象不同,数据存储为序列化的字节数组
  3. RocksDB可以根据可用磁盘空间进行扩展,并且是唯一支持增量快照的状态后端。
  4. 但是每个状态访问和更新都需要(反)序列化并可能从磁盘读取,这导致平均性能比内存状态后端慢一个数量级

场景

  • 具有非常大状态、长窗口、大键/值状态的作业。
  • 所有高可用性设置

旧版

  • MemoryStateBackend(内存,不推荐在生产场景使用)
  • FsStateBackend(文件系统上,本地文件系统、HDFS, 性能更好,常用)
  • RocksDBStateBackend (无需担心 OOM 风险,是大部分时候的选择)

配置

方式一:可以flink-conf.yaml使用配置键在 中配置默认状态后端state.backend。
可以配置的值是hashmap (HashMapStateBackend)、rocksdb (EmbeddedRocksDBStateBackend)
或实现状态后端工厂StateBackendFactory的类的完全限定类名

  • 全局配置例子一
# The backend that will be used to store operator state checkpoints
state.backend: hashmap
​
# Optional, Flink will automatically default to JobManagerCheckpointStorage
# when no checkpoint directory is specified.
state.checkpoint-storage: jobmanager
  • 全局配置例子二
state.backend: rocksdb
state.checkpoints.dir: file:///checkpoint-dir/
​
# Optional, Flink will automatically default to FileSystemCheckpointStorage
# when a checkpoint directory is specified.
state.checkpoint-storage: filesystem

方式二:代码 单独job配置例子

  • 代码配置一
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStateBackend(new HashMapStateBackend());
env.getCheckpointConfig().setCheckpointStorage(new JobManagerCheckpointStorage());
  • 代码配置二
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStateBackend(new EmbeddedRocksDBStateBackend());
env.getCheckpointConfig().setCheckpointStorage("file:///checkpoint-dir");
//或者
env.getCheckpointConfig().setCheckpointStorage(new FileSystemCheckpointStorage("file:///checkpoint-dir"));

注:使用 RocksDBStateBackend 需要加依赖

<dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-statebackend-rocksdb_${scala.version}</artifactId>
            <version>1.13.1</version>
</dependency>

sum()、maxBy() 等函数底层源码也是有ValueState进行状态存储

代码示例:

需求:
根据订单进行分组,统计找出每个商品最大的订单成交额
不用maxBy实现,用ValueState实现

    /**
     * 使用valueState实现maxBy功能,统计分组内订单金额最高的订单
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {//构建执行任务环境以及任务的启动的入口, 存储全局相关的参数
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
​
        env.setParallelism(1);DataStream<String> ds = env.socketTextStream("127.0.0.1", 8888);DataStream<Tuple3<String, String, Integer>> flatMapDS = ds.flatMap(new RichFlatMapFunction<String, Tuple3<String, String, Integer>>() {
​
​
            @Override
            public void flatMap(String value, Collector<Tuple3<String, String, Integer>> out) throws Exception {
                String[] arr = value.split(",");
                out.collect(Tuple3.of(arr[0], arr[1], Integer.parseInt(arr[2])));
            }
        });
​
​
        //一定要key by后才可以使用键控状态ValueState
        SingleOutputStreamOperator<Tuple2<String, Integer>> maxProductOrder = flatMapDS.keyBy(new KeySelector<Tuple3<String,String,Integer>, String>() {
            @Override
            public String getKey(Tuple3<String, String, Integer> value) throws Exception {
                return value.f0;
            }
        }).map(new RichMapFunction<Tuple3<String, String, Integer>, Tuple2<String, Integer>>() {
            private ValueState<Integer> valueState = null;@Override
            public void open(Configuration parameters) throws Exception {
                valueState = getRuntimeContext().getState(new ValueStateDescriptor<Integer>("total", Integer.class));
            }@Override
            public Tuple2<String, Integer> map(Tuple3<String, String, Integer> tuple3) throws Exception {
                // 取出State中的最大值
                Integer stateMaxValue = valueState.value();Integer currentValue = tuple3.f2;if (stateMaxValue == null || currentValue > stateMaxValue) {
                    //更新状态,把当前的作为新的最大值存到状态中
                    valueState.update(currentValue);
                    return Tuple2.of(tuple3.f0, currentValue);
                } else {
                    //历史值更大
                    return Tuple2.of(tuple3.f0, stateMaxValue);
                }
            }
        });
​
        maxProductOrder.print();
​
        env.execute("valueState job");
    }
  

Checkpoint-SavePoint和端到端(end-to-end)状态一致性

Checkpoint与savepoint
  • Flink中所有的Operator的当前State的全局快照,默认情况下 checkpoint 是禁用的
  • Checkpoint是把State数据定时持久化存储,防止丢失
  • 手工调用checkpoint,叫 savepoint,主要是用于flink集群维护升级等
  • 底层使用了Chandy-Lamport 分布式快照算法,保证数据在分布式环境下的一致性
  • 开箱即用,Flink 捆绑了这些检查点存储类型:
    作业管理器检查点存储 JobManagerCheckpointStorage
    文件系统检查点存储 FileSystemCheckpointStorage
配置
//全局配置checkpoints
state.checkpoints.dir: hdfs:///checkpoints///作业单独配置checkpoints
env.getCheckpointConfig().setCheckpointStorage("hdfs:///checkpoints-data/");
//全局配置savepoint
state.savepoints.dir: hdfs:///flink/savepoints
Savepoint 与 Checkpoint 的不同
  • 类似于传统数据库中的备份与恢复日志之间的差异
  • Checkpoint 的主要目的是为意外失败的作业提供【重启恢复机制】,
  • Checkpoint 的生命周期由 Flink 管理,即 Flink 创建,管理和删除 Checkpoint - 无需用户交互
  • Savepoint 由用户创建,拥有和删除, 主要是【升级 Flink 版本】,调整用户逻辑
  • 除去概念上的差异,Checkpoint 和 Savepoint 的当前实现基本上使用相同的代码并生成相同的格式
端到端(end-to-end)状态一致性
  • 数据一致性保证都是由流处理器实现的,也就是说都是在Flink流处理器内部保证的
  • 在真实应用中,了流处理器以外还包含了数据源(例如Kafka、Mysql)和输出到持久化系统(Kafka、Mysql、Hbase、CK)
  • 端到端的一致性保证,是意味着结果的正确性贯穿了整个流处理应用的各个环节,每一个组件都要保证自己的一致性。
Source

需要外部数据源可以重置读取位置,当发生故障的时候重置偏移量到故障之前的位置

内部

依赖Checkpoints机制,在发生故障的时可以恢复各个环节的数据

Sink

当故障恢复时,数据不会重复写入外部系统,常见的就是 幂等和事务写入(和checkpoint配合)

配置
		//两个检查点之间间隔时间,默认是0,单位毫秒
        env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);//Checkpoint过程中出现错误,是否让整体任务都失败,默认值为0,表示不容忍任何Checkpoint失败
        env.getCheckpointConfig().setTolerableCheckpointFailureNumber(5);//Checkpoint是进行失败恢复,当一个 Flink 应用程序失败终止、人为取消等时,它的 Checkpoint 就会被清除
        //可以配置不同策略进行操作
        // DELETE_ON_CANCELLATION: 当作业取消时,Checkpoint 状态信息会被删除,因此取消任务后,不能从 Checkpoint 位置进行恢复任务
        // RETAIN_ON_CANCELLATION(多): 当作业手动取消时,将会保留作业的 Checkpoint 状态信息,要手动清除该作业的 Checkpoint 状态信息
        env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);//Flink 默认提供 Extractly-Once 保证 State 的一致性,还提供了 Extractly-Once,At-Least-Once 两种模式,
        // 设置checkpoint的模式为EXACTLY_ONCE,也是默认的,
        env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);//设置checkpoint的超时时间, 如果规定时间没完成则放弃,默认是10分钟
        env.getCheckpointConfig().setCheckpointTimeout(60000);//设置同一时刻有多少个checkpoint可以同时执行,默认为1就行,以避免占用太多正常数据处理资源
        env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);
​
​
        //设置了重启策略, 作业在失败后能自动恢复,失败后最多重启3次,每次重启间隔10s
        env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, 10000));
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值