flink state原理,TTL,状态后端,数据倾斜一文全

Flink实例:状态管理State 过期时间TTL 一旦设置了 TTL,那么如果上次访问的时间戳 + TTL 超过了当前时间,则表明状态过期了(这是一个简化的说法,严谨的定义请参考org.apache.flink.runtime.state.ttl.TtlUtils类中关于 expired 的实现)。对于 RocksDB 的状态清理,则是通过 JNI 来调用 C++ 语言编写的 FlinkCompactionFilter 来实现,底层是通过 RocksDB 提供的后台 Compaction 操作来实现对失效状态过滤的。如果启用,则每次状态访问都将触发它。.. 阅读详情

1. 状态、状态后端、Checkpoint 三者之间的区别及关系?

拿五个字做比喻:“铁锅炖大鹅”,铁锅是状态后端,大鹅是状态,Checkpoint 是炖的动作。

  1. 状态:本质来说就是数据,在 Flink 中,其实就是 Flink 提供给用户的状态编程接口。比如 flink 中的 MapState,ValueState,ListState。

  2. 状态后端:Flink 提供的用于管理状态的组件,状态后端决定了以什么样数据结构,什么样的存储方式去存储和管理我们的状态。Flink 目前官方提供了 memory、filesystem,rocksdb 三种状态后端来存储我们的状态。
    但!flink1.13后 对状态后端做了整合,只有这两种了

  • HashMapStateBackend
  • EmbeddedRocksDBStateBackend

老版本(flink-1.12 版及以前) Fsstatebackend MemoryStatebackend RocksdbStateBackend
新版本中,Fsstatebackend 和 MemoryStatebackend 整合成了 HashMapStateBackend 而且 HashMapStateBackend 和 EmBeddedRocksDBStateBackend 所生成的快照文件也统一了格式,因而 在 job 重新部署或者版本升级时,可以任意替换 statebackend

  1. Checkpoint(状态管理):Flink 提供的用于定时将状态后端中存储的状态同步到远程的存储系统的组件或者能力。为了防止 long run 的 Flink 任务挂了导致状态丢失,产生数据质量问题,Flink 提供了状态管理(Checkpoint,Savepoint)的能力把我们使用的状态给管理起来,定时的保存到远程。然后可以在 Flink 任务 failover 时,从远程把状态数据恢复到 Flink 任务中,保障数据质量。

2 算子状态与键控状态的区别

2.1 算子状态

  •  算子状态,是每个 subtask 自己持有一份独立的状态数据(但如果在失败恢复后,算子并行度发 生变化,则状态将在新的 subtask 之间均匀分配);
  •  算子函数实现 CheckpointedFunction 后,即可使用算子状态;
  •  算子状态,通常用于 source 算子中;其他场景下建议使用 KeyedState(键控状态);
  • 算子状态,在逻辑上,由算子 task 下所有 subtask 共享; 如何理解:正常运行时,subtask 自己读写自己的状态数据;而一旦 job 重启且带状态算子发生了并行度的变化,则 之前的状态数据将在新的一批 subtask 间均匀分配

2.2 键控状态

  •  键控状态,只能应用于 KeyedStream 的算子中(keyby 后的处理算子中);
  •  算子为每一个 key 绑定一份独立的状态数据;

在这里插入图片描述

2.3 算子状态api

要使用算子状态(operator state),需要让算子函数实现 CheckpointedFunction 接口;

/*** * @author hunter.d * @qq 657270652 * @wx haitao-duan * @date 2022/4/10 **/
public class OperatorStateTest {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        conf.setString("execution.savepoint.path", "D:\\ckpt\\27270525e8f166834f2bbf7c617ad6d3\\chk-11");
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(conf);
        env.enableCheckpointing(2000);
        env.getCheckpointConfig().setCheckpointStorage("file:///d:/ckpt");
        DataStreamSource<String> source = env.socketTextStream("localhost", 9999);
        //以下两个 map 算子,其中一个是带状态的 
        // 如果修改代码逻辑(如调整两个 map 算子顺序),且没有设置 uid,则从 savepoints 恢复时将失败
        source.map(new StatefulMapFunc()).uid("stateful-mapfunc-001").setParallelism(2).map(new NoStateMapFunc()).setParallelism(1).print().setParallelism(1);
        env.execute();
    }

    public static class NoStateMapFunc implements MapFunction<String, String> {
        @Override
        public String map(String value) throws Exception {
            return value.toUpperCase();
        }
    }

    // 带状态的 map 函数(将接收的字符串记在状态中,以不断拼接新数据返回) 

    public static class StatefulMapFunc extends RichMapFunction<String, String> implements CheckpointedFunction {
        ListState<String> lstState;

        /*** 正常的 map 映射逻辑方法 */

        @Override
        public String map(String value) throws Exception {
            lstState.add(value);
            StringBuilder sb = new StringBuilder();
            for (String s : lstState.get()) {
                sb.append(s).append(",");
            }
            return sb.toString();
        }

        /*** checkpoint 触发时会调用的方法 */
        @Override
        public void snapshotState(FunctionSnapshotContext context) throws Exception {
        }

        /*** 初始化算子任务时会调用的方法,以加载、初始化状态数据 */
        @Override
        public void initializeState(FunctionInitializationContext context) throws Exception {
            lstState = context.getOperatorStateStore().getListState(new ListStateDescriptor<String>("lst", String.class));
            int indexOfThisSubtask = getRuntimeContext().getIndexOfThisSubtask();
            Iterable<String> iter = lstState.get();
            Iterator<String> it = iter.iterator(); 
            
            // 用于观察 task 失败恢复后的状态恢复情况 
            System.out.println("-------" + indexOfThisSubtask + " - 初始化时,打印状态:-----");
            while (it.hasNext()) {
                System.out.println(indexOfThisSubtask + ":" + it.next());
            }
            System.out.println("-------" + indexOfThisSubtask + " -初始化时,打印状态:-----");
        }
    }
}
        

2.4 键控状态api

要使用键控状态(Keyed State),需要在实现 RichFunction 的函数中;

 public class _15_ChannelEventsCntMapFunc extends RichMapFunction<EventLog, String> {
    ValueState<Integer> valueState;

    @Override
    public void open(Configuration parameters) throws Exception {
        StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.milliseconds(2000)).cleanupFullSnapshot().neverReturnExpired().useProc
        essingTime().updateTtlOnReadAndWrite().build();
        ValueStateDescriptor<Integer> desc = new ValueStateDescriptor<>("cnt", Integer.class);
        desc.enableTimeToLive(ttlConfig); // 获取单值状态管理器 
        valueState = getRuntimeContext().getState(desc);
    }

    @Override
    public String map(EventLog eventLog) throws Exception {
        // 来一条数据,就对状态更新 
        valueState.update((valueState.value() == null ? 0 : valueState.value()) + 1);
        return eventLog.getChannel() + " : " + valueState.value();
    }
}

3 HashMapStateBackend 状态后端

HashMapStateBackend:

  •  状态数据是以 java 对象形式存储在 heap 内存中;

  •  内存空间不够时,也会溢出一部分数据到本地磁盘文件;

  •  可以支撑大规模的状态数据;(只不过在状态数据规模超出内存空间时,读写效率就会明显降低)

  • 对于 KeyedState 来说:
    HashMapStateBackend 在内存中是使用 CopyOnWriteStateMap 结构来存储用户的状态数据; 注意,此数据结构类,名为 Map,实非 Map,它其实是一个单向链表的数据结构

  • 对于 OperatorState 来说:
    在这里插入图片描述
    可以清楚看出,它底层直接用一个 Map 集合来存储用户的状态数据:状态名称 --> 状态 List

4 EmBeddedRocksDbStateBackend 状态后端

  •  状态数据是交给 rocksdb 来管理;
  •  Rocksdb 中的数据是以序列化的 kv 字节进行存储;
  •  Rockdb 中的数据,有内存缓存的部分,也有磁盘文件的部分;
  •  Rockdb 的磁盘文件数据读写速度相对还是比较快的,所以在支持超大规模状态数据时,数据的 读写效率不会有太大的降低

注意:上述 2 中状态后端,在生成 checkpoint 快照文件时,生成的文件格式是完全一致的; 所以,用户的 flink 程序在更改状态后端后,重启时依然可以加载和恢复此前的快照文件数据;
老版本中,状态与状态后端的关系是:
在这里插入图片描述

5 状态数据结构介绍

5.1 算子状态提供的数据结构

ListState , UnionListState
UnionListState 和普通 ListState 的区别:

  1. UnionListState 的快照存储数据,在系统重启后,list 数据的重分配模式为: 广播模式; 在每个 subtask 上都拥有一份完整的数据;
  2. ListState 的快照存储数据,系统重启后,list 数据的重分配模式为: round-robin 轮询平均分配

5.2 键控状态提供的数据结构

 ValueState  ListState  MapState  ReducingState  AggregateState

6 Reducing 聚合状态

用户传入一个增量聚合函数后,状态实现自动增量聚合(输入数据与聚合结果类型必须一致)

// 获取一个 reduce 聚合状态 
    reduceState =runtimeContext.getReducingState(new ReducingStateDescriptor<Integer>("reduceState",new ReduceFunction<Integer>()

    {
        @Override public Integer reduce (Integer value1, Integer value2) throws Exception {
        return value1 + value2;
    }
    },Integer .class));

7 广播状态

/*** * @author hunter.d * @qq 657270652 * @wx haitao-duan * @date 2022/4/10 **/
public class OperatorStateTest {
    // 主数据流 
    SingleOutputStreamOperator<Student> s1;
    // 待广播出去的流
    SingleOutputStreamOperator<StuInfo> s2;
    // 定义广播状态的状态描述对象
    MapStateDescriptor<Integer, StuInfo> stateDescriptor = new MapStateDescriptor<>("info", Integer.class, StuInfo.class);
    // 将 s2 流广播出去 BroadcastStream<StuInfo>
    stuInfoBroadcastStream =s2.broadcast(stateDescriptor);
    // 用主数据流 connect 连接 广播数据流,并处理
    s1.connect(stuInfoBroadcastStream).

    process(new BroadcastProcessFunction<Student, StuInfo, String>() {
        @Override public void processElement (Student student, ReadOnlyContext
        readOnlyContext, Collector < String > collector) throws Exception
        {
            // 对 "主流" 中的元素进行处理 
            readOnlyContext.getBroadCastState(); // 只读状态
        }
        @Override public void processBroadcastElement (StuInfo stuInfo, Context context, Collector < String > collector) throws
        Exception {
            // 对 "广播流" 中的元素进行处理
            context.getBroadCastState(); // 可读可写 
        }
    });

}

8. flink重启时,修改并行度,state会发生什么变化?键值状态分区策略,解决数据倾斜

假设原来是3个并行度
3个并行度

重启之后给两个并行度,state会发生什么呢?他依然可以加载之前的快照数据

这里面引入一下 : subtask 是什么呢,相当于 每一个算子,就是一个subtask,像下面的 4个sink 就是4个subtask,4个并行度。
在这里插入图片描述

那么说回来,3个并行度 改成了两个,少了一个,这个subtask上存储的state 要怎么办呢。
假设你用的是liststate。重启的时候 ,会自动做分配到剩余的两个state里

在这里插入图片描述
也可能是,直接重新分配给某一个state,以前 三个并行度,分别读kafka的三个分区,1分区 1000,2 分区 500, 3分区 800
重新分配后,就变成了 1分区 1000+3分区 800 ; 2 分区 500 这种情况。

在键值状态API的设计思路小节中,我们提到键值状态在重分布时要和KeyedStream的哈希数据分区策略保持完全一致。原理理解起来简单,但实际上Flink键值状态重分布的机制在此基础上还做了很多的性能优化,本节我们就详细剖析键值状态重分布的过程,掌握这部分知识将会对我们在生产环境中解决数据倾斜问题有很大的帮助。

我们以电商场景中计算每种商品累计销售额的场景为例,逻辑数据流为Source→KeyBy\Map→Sink,我们在KeyBy\Map算子中使用键值状态ValueState来保存每种商品的累计销售额。

接下来我们看看ValueState键值状态在KeyBy\Map算子并行度从2变为3时键值状态的重分布过程。如图6-28所示,我们用parallelism代表算子并行度,假设KeyedStream的哈希数据分区策略的计算公式为SubTask(key)=hash(key)%parallelism(符号%代表取余计算),该计算公式用于计算某个key的数据要被发往KeyBy\Map算子的SubTask下标。

当KeyBy\Map算子的并行度为2时,哈希数据分区策略就为SubTask(key)=hash(key)%2,假设这时经过计算后,key为商品3的数据会被发送到KeyBy\Map[1]中,那么商品3的累计销售额的状态数据就会存储在KeyBy\Map[1]本地。当用户将KeyBy\Map算子的并行度扩展为3后,哈希数据分区策略就变为了SubTask(key)=hash(key)%3,由于数据分区策略的计算公式变化了,因此每一个key的数据要发往的SubTask也会发生改变。假设这时key为商品3的数据会被发送到KeyBy\Map[0]中,那么商品3的累计销售额状态数据必然要被重分布到KeyBy\Map[0]中,如图所示。

在这里插入图片描述
虽然键值状态的重分布策略能够降低用户的开发成本,但是这种重分布策略却对键值状态重分布的性能提出了巨大的挑战。如图6-28所示,当算子并行度为2时,每个SubTask在执行快照时会将本地的状态数据顺序地写入到远程分布式文件系统中,SubTask0和SubTask1分别写入文件1和文件2。当算子并行度变为3后,根据新的Hash分区策略计算,key为商品0、商品3、商品6和商品9的数据要被恢复到SubTask0中,那么SubTask0就要同时读取文件1和文件2,SubTask1和SubTask2的恢复过程也相同,都分别需要从文件1和文件2中恢复一部分key的状态数据。

这时我们发现如果要让每个SubTask都完整且正确的恢复状态数据,就需要让每个SubTask都从分布式文件系统中读取到所有的快照文件,然后再过滤出属于当前SubTask的key的状态数据,但是按照这样的流程执行,就会出现以下两个问题。

  • 状态恢复时的性能问题:在算子以新的并行度启动并从快照恢复时,算子的每个SubTask都会读取大量不属于当前SubTask的key的状态数据,同时还需要从中筛选出属于当前SubTask的状态数据,而这会导致SubTask的启动过程耗费大量的时间,作业的恢复过程很漫长。举例来说,如果算子的并行度为500,每一个SubTask中都有100万个key的状态数据,那么整个作业总计会有5亿个key,这时如果我们将算子并行度扩展为1000,那么对这1000个SubTask来说,每一个SubTask都要读取到这5亿个key的快照文件,然后再过滤出属于自己的key的状态数据,但是平均下来每个SubTask最终只会保留50万个key的状态数据,其余的4.995亿个key的数据都会被过滤。
  • 分布式文件系统的稳定性问题:在算子从快照时,所有的SubTask都会对分布式文件系统发起大量读取相同文件的请求,这对分布式文件系统稳定性也会造成影响,并且随着算子并行度的增大,这种情况会越来越严重。

综上所述,使用该方案来恢复状态数据时,性能是无法达到预期的。其低效的原因就在于从状态恢复时,SubTask不知道分布式文件系统中的每一份快照文件中存储了哪些key的状态数据,也不知道这些key的状态数据在快照文件中的偏移量,所以只能全量读取后再按照key一个一个的进行过滤。

这里插一句,在20240125 此时此刻,flink计划做的2.0中最核心的一块就是状态的存算分离,解决的就是大状态的性能场景问题,与这里引出的状态重分配导致的问题,本质上是一个情况,所以这个问题正常情况来说,flink2.0上线以后,可以解决。

9.Flink State TTL 是怎么做到数据过期的?首先我们来想想,要做到 TTL 的话,要具备什么条件呢?

想想 Redis 的 TTL 设置,如果我们要设置 TTL 则必然需要给一条数据给一个时间戳,只有这样才能判断这条数据是否过期了。

在 Flink 中设置 State TTL,就会有这样一个时间戳,具体实现时,Flink 会把时间戳字段和具体数据字段存储作为同级存储到 State 中。

举个例子,我要将一个 String 存储到 State 中时:

  1. ⭐ 没有设置 State TTL 时,则直接将 String 存储在 State 中
  2. ⭐ 如果设置 State TTL 时,则 Flink 会将 <String, Long> 存储在 State 中,其中 Long 为时间戳,用于判断是否过期。

接下来以 FileSystem 状态后端下的 MapState 作为案例来说:

⭐ 如果没有设置 State TTL,则生产的 MapState 的字段类型如下(可以看到生成的就是 HeapMapState 实例):
在这里插入图片描述
⭐ 如果设置了 State TTL,则生成的 MapState 的字段类型如下(可以看到使用到了装饰器的设计模式生成是 TtlMapState):
在这里插入图片描述

注意:
任务设置了 State TTL 和不设置 State TTL 的状态是不兼容的。这里大家在使用时一定要注意。防止出现任务从 Checkpoint 恢复不了的情况。但是你可以去修改 TTL 时长,因为修改时长并不会改变 State 存储结构。

注意:
 存活时长的计时器可以在数据被读、写时重置;
 Ttl 存活管理粒度是到元素级的(如 liststate 中的每个元素,mapstate 中的每个 entry)

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

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

  2. cleanupFullSnapshot
    在进行全量快照(checkpoint)时,清理掉过期数据; 注意:只是在生成的 checkpoint 数据中不包含过期数据;在本地状态空间中,并没有做清理; 本策略,针对“快照”生效

  3. cleanupInRocksdbCompactFilter 只针对 rocksdbStateBackend 有效; 它是利用 rocksdb 的 compact 功能,在 rocksdb 进行 compact 时,清除掉过期数据; 本策略,针对“本地状态空间”,且只用于 EmbeddedRocksDbStateBackend

10.Flink SQL API State TTL 的过期机制是 onCreateAndUpdate 还是onReadAndWrite

⭐ 结论:Flink SQL API State TTL 的过期机制目前只支持 onCreateAndUpdate,DataStream API 两个都支持

在这里插入图片描述
⭐ 剖析:

  • onCreateAndUpdate:是在创建 State 和更新 State 时【更新 State TTL】
  • onReadAndWrite:是在访问 State 和写入 State 时【更新 State TTL】

⭐ 实际踩坑场景:Flink SQL Deduplicate 写法,row_number partition by user_id order by proctime asc,此 SQL 最后生成的算子只会在第一条数据来的时候更新 state,后续访问不会更新 state TTL,因此 state 会在用户设置的 state TTL 时间之后过期。

5.operator-state 和 keyed-state 两者的区别?最大并行度又和它们有什么关系?举个生产环境中经常出现的案例,当用户停止任务、更新代码逻辑并且改变任务并发度时,两种 state 都是怎样进行恢复的?

⭐ 总结如下:
在这里插入图片描述

⭐ operator-state:

在这里插入图片描述

  • ⭐ 状态适用算子:所有算子都可以使用 operator-state,没有限制。

  • ⭐ 状态的创建方式:如果需要使用 operator-state,需要实现 CheckpointedFunction 或 ListCheckpointed 接口

  • ⭐ DataStream API 中,operator-state 提供了 ListState、BroadcastState、UnionListState 3 种用户接口

  • ⭐ 状态的存储粒度:以单算子单并行度粒度访问、更新状态

  • ⭐ 并行度变化时:a. ListState:均匀划分到算子的每个 sub-task 上,比如 Flink Kafka Source 中就使用了 ListState 存储消费 Kafka 的 offset,其 rescale 如下图在这里插入图片描述

  • BroadcastState:每个 sub-task 的广播状态都一样 c. UnionListState:将原来所有元素合并,合并后的数据每个算子都有一份全量状态数据
    在这里插入图片描述

⭐ keyed-state:

在这里插入图片描述

  • ⭐ 状态适用算子:keyed-stream 后的算子使用。注意这里很多同学会犯一个错误,就是大家会认为 keyby 后面跟的所有算子都使用的是 keyed-state,但这是错误的 ❌,比如有 keyby.process.flatmap,其中 flatmap 中使用状态的话是 operator-state
  • ⭐ 状态的创建方式:从 context 接口获取具体的 keyed-state
  • ⭐ DataStream API 中,keyed-state 提供了 ValueState、MapState、ListState 等用户接口,其中最常用 ValueState、MapState
  • ⭐ 状态的存储粒度:以单 key 粒度访问、更新状态。举例,当我们使用 keyby.process,在 process 中处理逻辑时,其实每一次 process 的处理 context 都会对应到一个 key,所以在 process 中的处理都是以 key 为粒度的。这里很多同学会犯一个错 ❌,比如想在 open 方法中访问、更新 state,这是不行的,因为 open 方法在执行时,还没有到正式的数据处理环节,上下文中是没有 key 的。
  • ⭐ 并行度变化时:keyed-state 的重新划分是随着 key-group 进行的。其中 key-group 的个数就是最大并发度的个数。其中一个 key-group 处理一段区间 key 的数据,不同 key-group 处理的 key 是完全不同的。当任务并行度变化时,会将 key-group 重新划分到算子不同的 sub-task 上,任务启动后,任务数据在做 keyby 进行数据 shuffle 时,依然能够按照当前数据的 key 发到下游能够处理这个 key 的 key-group 中进行处理,如下图所示。注意:最大并行度和 key-group 的个数绑定,所以如果想恢复任务 state,最大并行度是不能修改的。大家需要提前预估最大并行度个数。
    在这里插入图片描述

11.ValueState 和 MapState 各自适合的应用场景?

  1. ⭐ ValueState
  • 应用场景:简单的一个变量存储,比如 Long\String 等。如果状态后端为 RocksDB,极其不建议在 ValueState 中存储一个大 Map,这种场景下序列化和反序列化的成本非常高,这种常见适合使用 MapState。其实这种场景也是很多小伙伴一开始使用 State 的误用之痛,一定要避免。
  • TTL:针对整个 Value 起作用
  1. ⭐ MapState
  • 应用场景:和 Map 使用方式一样一样的
  • TTL:针对 Map 的 key 生效,每个 key 一个 TTL
Flink状态管理实战:从核心原理到生产环境调优指南 在分布式流处理系统中,状态管理是实现复杂计算逻辑和保证数据一致性的核心技术。其核心原理在于通过维护计算上下文信息,使流处理从无状态转换进化到有状态计算,从而支撑实时聚合、会话分析和事件模式匹配等高级场景。从技术价值看,高效的状态管理是保障作业正确性、稳定性和实现精确一次(Exactly-Once)容错语义的基石,直接决定了生产系统的可靠性。在实际应用场景中,状态后端(如RocksDB)的选型与配置、Checkpoint机制的调优以及状态生存时间(TTL)的设置,是解决状态膨胀和性能瓶颈的关键。本文聚焦于Ap 阅读详情

相关推荐

Flink数据倾斜问题诊断与十二种解决方案

数据倾斜是大数据处理中的常见挑战,指特定键值或分区数据量远高于平均水平,导致计算资源分配不均。其核心原理在于哈希分片机制下,非均匀分布的数据会使部分节点过载。这不仅降低系统吞吐量,还会引发背压、检查点超时等问题。在实时计算框架如Flink中,数据倾斜常表现为TaskManager负载不均衡、Kafka消费延迟等典型症状。通过两阶段聚合、热点Key隔离、动态负载均衡等技术,可有效分散计算压力。这些优化手段在电商实时分析、金融风控等场景尤为重要,例如应对大促期间的用户行为日志倾斜。合理运用监控指标如numRec

weixin_33831196的博客 400

Flink系列之:State Time-To-Live (TTL)

定期压缩可以加快过期状态条目的清理速度,特别是对于很少访问的状态条目。您可以将其设置为 0 以关闭定期压缩,或设置一个较小的值以加速过期状态条目清理,但它会触发更多压缩。在 NeverReturnExpired 的情况下,过期状态的行为就好像它不再存在一样,即使它仍然需要被删除。默认情况下,过期值会在读取时显式删除,例如 ValueState#value,并在配置的状态后端支持的情况下定期在后台进行垃圾收集。在当前实现下,本地状态不会被清除,但在从以前的快照恢复时,它不会包括删除的过期状态。

zhengzaifeidelushang的博客 1109

【Flink 30天】Day30 Flink 高频面试题 20 道(含架构/时间/状态/Checkpoint/SQL/排查)

Flink 最全面试题整理:涵盖核心架构、时间Watermark、状态Checkpoint、线上运维、FlinkSQL,附知识体系脑图。

huangrunxing的专栏 440

详解 Flink 状态管理

文章目录1.前言2.状态是什么东西?有了状态能做什么?3.为什么离线计算中不提状态,实时计算老是提到状态这个概念?状态到底在实时计算中解决了什么问题?3.1 离线任务真的是没有状态、状态管理这些个概念这个概念嘛?3.2 实时任务真的只能依赖状态、状态管理嘛?4.有了状态、为什么又出现了状态管理的概念?5.怎么学习 Flink 中的状态、状态管理相关的概念呢?6.Flink 中状态的分类?7.Flink 中状态的使用方式?8.Flink 状态后端的分类及使用建议?9.Flink 中状态的能力扩展 - TTL?

qq_24095055的博客 1819

Flink Barrier与Checkpoint机制深度解析:从原理到Exactly-Once实战

在分布式流处理系统中,容错与状态一致性是保障数据准确性的基石。其核心原理在于通过分布式快照技术,在不停机的情况下捕获应用全局一致性状态。这一技术通过轻量级的控制信号(Barrier)在数据流中传播,精准触发各计算节点的状态持久化,从而在故障时能精准回溯与恢复,确保每条数据对状态的影响只生效一次,实现高效的容错。该机制对金融交易、实时风控等高要求场景至关重要,能有效解决作业恢复慢、状态膨胀及反压等工程难题。本文将以Apache Flink的Barrier与Checkpoint机制为例,深入剖析其如何保障流处理

weixin_30924087的博客 390

Flink实时计算核心原理与实践:从时间状态到流处理架构深度解析

流处理技术是处理海量、高速、持续数据流的核心架构范式,其核心在于对无界数据的有序处理与状态管理。其基本原理是通过事件时间、水位线等机制处理乱序数据,并借助状态管理和检查点机制保障计算的一致性与容错性。这项技术的核心价值在于实现从传统批处理的事后分析到实时流处理的事中决策的跨越,支撑低延迟、高吞吐的数据处理需求。典型应用场景包括实时风控、实时监控、实时推荐和实时ETL等。本文以Apache Flink为例,深入剖析其四大基石——时间、状态、检查点和窗口,并结合生产环境中的状态后端选型与检查点调优等热词,提供从

weixin_30323631的博客 346

Flink实际问题以及知识点

Flink对线面试官1 状态原理1.1 状态、状态后端、Checkpoint 三者之间的区别及关系?1.2 把状态后端从 FileSystem 变为 RocksDB 后,Flink 任务状态存储会发生那些变化?1.3.什么样的业务场景你会选择 filesystem,什么样的业务场景你会选 rocksdb 状态后端?1.4 Flink SQL API State TTL 的过期机制是 onCreateAndUpdate 还是 onReadAndWrite2 时间窗口2.1 watermark 到底是干啥的?应

一个写湿的程序猿 5020

Flink的调优方法

Flink 调优是一个迭代和权衡的过程,没有银弹。先保证正确,再优化性能。从资源配置开始,再到作业逻辑。监控驱动,数据说话,不要盲目调整参数。一次只调整一个变量,观察效果。最好的调优往往来自对业务逻辑的深刻理解,比如优化数据倾斜的 Key 设计,比调整任何参数都有效。理解 Flink 的内部原理(窗口、状态、网络),是进行有效调优的基础。

猪猪 301

如何解决 Flink 的状态膨胀问题

Flink状态膨胀问题优化方案 状态膨胀问题主要由无限制状态积累、大键值存储、不合理数据结构及数据倾斜等引起。核心优化措施包括: TTL设置:通过DataStream API或SQL(全局配置/Hint/编译计划)为状态设置生存时间 状态后端选择:大状态场景优先使用RocksDB,并调优内存管理、压缩策略及增量Checkpoint 业务逻辑优化:避免无限ListState,改用MapState分区存储;优化窗口聚合与连接操作 运维监控:通过Metrics跟踪状态大小,处理数据倾斜(如加盐),必要时重启作业重

zfqzpp的专栏 913

Flink State TTL 详解

Flink 1.13 版本 在某些场景下 Flink 用户状态一直在无限增长,一些用例需要能够自动清理旧的状态。例如,作业中定义了超长的时间窗口,或者在动态表上应用了无限范围的 GROUP BY 语句。此外,目前开发人员需要自己完成 TTL 的临时实现,例如使用可能不节省存储空间的计时器服务。还有一个比较重要的点是一些法律法规也要求必须在有限时间内访问数据。 对于这些情况,旧版本的 Flink 并不能很好解决,因此 Apache Flink 1.6.0 版本引入了状态 TTL 特性。该特性可以让 Key.

SmartSi 3726

【Flink】Flink state 状态生存时间(TTL)

一个时间的生存期(TTL)可以被分配给任何类型的被Keys化状态。如果配置了TTL并且状态值已过期,则将尽力清除存储的值,这将在下面更详细地讨论。 所有状态集合类型都支持每个条目的TTL。这意味着列表数据元和映射条目将独立过期。 为了使用状态TTL,必须首先构建StateTtlConfig配置对象。然后,可以通过传递配置在任何状态描述符中启用TTL函数: import org.apache.flink.api.common.state.StateTtlConfig; import org.apache.f.

九师兄 975

Flink实战进阶:State、Window核心机制与生产环境调优指南

在实时流处理领域,有状态计算是实现复杂业务逻辑的基石。其核心原理在于通过状态管理,让无界的数据流处理具备“记忆”能力,从而支持聚合、关联和模式检测等操作。这项技术的核心价值在于能够处理大规模、高吞吐的实时数据,并保证计算结果的准确性与一致性。典型的应用场景包括实时监控、风险控制、实时推荐和实时数仓等。本文聚焦于Apache Flink这一主流流处理框架,深入剖析其状态管理与窗口计算两大核心机制,并结合生产环境中的常见问题,如状态后端配置、异步I/O优化以及资源调优,提供从原理到实践的详细指导,帮助开发者构建

weixin_33806300的博客 321

大数据领域Flink的状态管理最佳实践

在流式处理领域,状态是Flink区别于其他框架的核心竞争力——它让流式应用能实现“记忆”(比如计算用户累计消费、实时去重、窗口聚合)。状态不一致:故障恢复后数据计算错误;性能瓶颈:Checkpoint超时、状态后端IO卡顿;运维困难:状态太大导致集群崩溃、版本升级丢失状态。这些问题的根源,往往是对Flink状态管理的原理理解不深或最佳实践缺失。本文将从原理剖析→实践落地→优化技巧三个层面,系统讲解Flink状态管理的最佳实践。清晰区分Keyed State与Operator State的适用场景;

软件工程实践的博客 962

Awesome Flink架构解析:深入理解Flink流批一体处理原理

Apache Flink作为当今最强大的流批一体处理框架,正在彻底改变大数据处理的方式。本文将深入解析Flink的架构设计原理,帮助新手和普通用户快速掌握这一革命性技术的核心机制。Flink流批一体处理框架通过统一的运行时引擎,为实时数据处理和批量分析提供了完美的解决方案。 ## 📊 Flink架构概述:分层设计理念 [![Flink松鼠图标](https://raw.gitcode.com

gitblog_00386的博客 818

Flink 回撤流(Retract Stream)深度剖析:从底层原理到生产调优

本文深入解析Flink回撤流的核心概念与生产实践。回撤流通过-U撤回旧值和+U写入新值的方式实现流式计算的更新语义,是Flink动态表的关键机制。文章详细剖析了回撤流的产生场景(GROUP BY聚合、Regular JOIN等)、RowKind传递原理及状态存储机制,并针对生产环境四大核心问题(Sink兼容性、数据膨胀、状态无限增长、乱序问题)给出了解决方案。重点介绍了MiniBatch、LocalGlobal、State TTL等优化手段,以及如何通过窗口聚合、Lookup Join等方式避免回撤流。最后

数据与算法架构提升之路专栏 216

BurpSuite实战:5分钟搞定Pikachu靶场表单爆破(附最新字典配置技巧)

本文通过Pikachu靶场实战,详细演示了如何使用BurpSuite的Intruder模块对Web登录表单进行暴力破解。从代理配置、请求捕获、集束炸弹模式设置,到载荷配置与结果分析,提供了完整的操作流程。文中还分享了2024年有效的字典获取与优化技巧,帮助安全测试人员快速定位弱口令漏洞。

weixin_29327977的博客 600

Apache—Flink实践

Apache—Flink实践

蓝魔的博客 321

嵌入式学习之QT学习---14 QT跨平台运行之把QT程序交叉编译到ARM开发板

想要把qt工程放到开发板上运行,就需要用到交叉编译。由于qt是跨平台的,所以只需要换个编译器编译一下就可以。 以“定时器”的例子为例,在移植之前还需要进行一个准备工作,在windows下运行的时候,电脑屏幕很大,但是运行的窗口只有一点点大,开发板也有外接屏幕,如何让运行窗口自动适配开发板的外接屏幕呢?令其占满屏幕显示,而不是一小块。 第一步:需要设置一下,先给ui布局,如果不布局,控件就不会随着屏幕的大小的变化而变化。 第二步:利用代码来获取屏幕的大小,给widget.cpp文件下添加如下代码 #inclu

qq_42822743的博客 5457

flink相关

Flink 把多个无 shuffle 算子链在一起,减少线程切换、网络开销,提升性能。下游处理慢 → 队列堆积 → 自动限制上游发送速率,防止 OOM。表格维度数据是否重复可能重复不重复Barrier 对齐不需要必须对齐状态一致性状态不丢,但可重复更新状态严格只更新一次性能高略低(对齐 + 快照开销)实现复杂度简单复杂,依赖 2PC适用场景监控、日志、允许重复支付、对账、实时数仓、金融下游算子处理不过来 → 自动限制上游发送速度 → 防止队列溢出、OOM、任务崩溃。

jiaque2015的博客 399

ESP32实战:破解校园网WPA2-Enterprise认证的完整指南

本文详细介绍了如何使用ESP32开发板破解校园网WPA2-Enterprise认证的完整指南。通过硬件准备、环境搭建、核心代码实现及常见问题排查,帮助开发者解决企业级WiFi连接难题,特别适用于校园网环境下的物联网设备开发。

weixin_29194817的博客 454

RK3576 USB3.0 DWC3控制器调试:PHY初始化失败排查指南

DWC3 是 Synopsys 公司推出的 USB3.0/3.1 控制器 IP,支持双角色(DRD)模式,可配置为 Host、Device 或 OTG。

小灰灰的博客 1177

【Flink 】从入门到生产实战:一篇文章吃透流处理核心

本文基于 Flink 1.18/1.19 重构了实时流处理核心知识,摒弃过时的 DataSet API 与旧版 Source/Sink 接口,聚焦流批一体的 DataStream API。重点梳理了 Flink 执行架构、提交流程、部署模式及新特性,涵盖 Source、Transformation、Sink 的最新写法,强调 Watermark 机制、Exactly-Once 保障、状态管理与数据倾斜应对策略。结合生产踩坑经验,为新手提供实战指导,助力高效构建低延迟、高可靠的实时数据处理系统。

zy123456nn的博客 404

petalinux2022.2启动文件编译配置

petalinux2021之前的版本里,导入目录components/yocto/下的“environment-setup-aarch64-xilinx-linux” 和 “layers/core/oe-init-build-env”的环境,能使用Yocto的devtool工具。(加入下面内容,先petalinux-build下载完成后才能有源码)制作 BOOT.BIN 启动文件:petalinux-package --boot --fsbl --fpga --u-boot --force。

wangjie36的博客 1390
上一篇: flink类加载器原理与隔离(flink jar包冲突)
下一篇: Flink/flinksql 语法 窗口与join 一文全 相关概念api汇总总结,底层process算子总结,与数据延迟处理,超时场景解决方案
Direction_Wind
博客等级 码龄8年 6438粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Direction_Wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值