Flink中KeyedStateStore实现--怎么做到一个Key对应一个State

Flink 笔记二 Flink的State--状态原理及原理剖析 1.状态类型 State按照是否有key划分为KeyedState和OperatorState Keyed State:KeyedStream流上的每一个Key都对应一个State (1)Keyed State 表示和Key相关的一种State,只能用于KeydStream类型数据集对应的Functions和 Operators之上。Keyed State是Operator State的特例,区别在于 Keyed State 事先按照key对数据集进行了分区,每个 Key State 仅对应ー个O 阅读详情

背景

在Flink中有两种基本的状态:Keyed State和Operator State,Operator State很好理解,一个特定的Operator算子共享同一个state,这是实现层面很好做到的。
但是 Keyed State 是怎么实现的?一般来说,正常的人第一眼就会想到:一个task绑定一个Keyd State,从网上随便查找资料就能发现正确的答案是:对于每一个Key会绑定一个State,但是这在Flink中是怎么实现的呢?
注意:这里我们只讲Flink中是怎么实现一个Key对应一个State的,其他细节并不细说,且state的backend为RocksDB

闲说杂谈

我们以ValueState类型的Keyed State举例:


ValueStateDescriptor<HoodieRecordGlobalLocation> indexStateDesc =
        new ValueStateDescriptor<>(
            "indexState",
            TypeInformation.of(HoodieRecordGlobalLocation.class));
ValueState<HoodieRecordGlobalLocation> indexState = context.getKeyedStateStore().getState(indexStateDesc)
....
indexState.update((HoodieRecordGlobalLocation) indexRecord.getCurrentLocation())

  • context.getKeyedStateStore().getState是获取对应key的State,最终的调用链如下:

     DefaultKeyedStateStore.getState -> getPartitionedState
                                                  ||
                                                  \/
     RocksDBKeyedStateBackend.getPartitionedState -> getOrCreateKeyedState -> createInternalState -> tryRegisterKvStateInformation
                                                  ||
                                                  \/
    
     RocksDBValueState.create(创建RocksDBValueState)                                                                             
                                          
    

    这里的 tryRegisterKvStateInformation会涉及到RocksDB ColumnFamily的创建:

    RocksDBOperationUtils.createStateInfo -> createColumnFamilyDescriptor 
    // createColumnFamilyDescriptor的部分代码:
    ColumnFamilyOptions options =
                 createColumnFamilyOptions(columnFamilyOptionsFactory, metaInfoBase.getName());
    if (ttlCompactFiltersManager != null) {
        ttlCompactFiltersManager.setAndRegisterCompactFilterIfStateTtl(metaInfoBase, options);
    }
    byte[] nameBytes = metaInfoBase.getName().getBytes(ConfigConstants.DEFAULT_CHARSET);
    ...
    return new ColumnFamilyDescriptor(nameBytes, options);
    
    

    其实最终会发现RocksDB的ColumnFamily是跟ValueStateDescriptor也就是描述符的名字有关的,这就是为什么描述符必须是唯一的,关于RocksDB的ColumnFamily,可以参考RocksDB 简介
    注意此时返回是key对应的一个State的ColumnFamily,该Family包括该task所有的key的value值

  • indexState.update 这里是更新indexState得值
    因为上一步得到只是该Task所对应的ColumanFamily所对应的所有的values,也就是* Flink中的Key-Groups*,(关于Key-Groups可以参考Apache-Flink深度解析-State)

      public void update(V value) {
         if (value == null) {
             clear();
             return;
         }
    
         try {
             backend.db.put(
                     columnFamily,
                     writeOptions,
                     serializeCurrentKeyWithGroupAndNamespace(),
                     serializeValue(value));
         } catch (Exception e) {
             throw new FlinkRuntimeException("Error while adding data to RocksDB", e);
         }
     }
    

    最终的调用链如下:

    RocksDBValueState.update -> serializeCurrentKeyWithGroupAndNamespace
            ||
            \/
    SerializedCompositeKeyBuilder.buildCompositeKeyNamespace
            ||
            \/
    serializeNamespace(namespace, namespaceSerializer) -> keyOutView.getCopyOfBuffer()   
    
    

    这里的keyOutView.getCopyOfBuffer是会获得的record的key,所以在backend.db.put方法中才会更新对应的Key值。
    但是什么时候Record的key信息会被写入到keyOutView中去呢?

  • Record的key何时被写到keyOutView中

    AbstractStreamTaskNetworkInput.emitNext -> processElement
           ||
           \/
    OneInputStreamTask.emitRecord
           ||
           \/
    OneInputStreamOperator.setKeyContextElement -> setKeyContextElement1 -> setKeyContextElement
    
           ||
           \/
    AbstractStreamOperator.setCurrentKey
           ||
           \/
    StreamOperatorStateHandler.setCurrentKey
           ||
           \/
    RocksDBKeyedStateBackend.setCurrentKey
           ||
           \/
    SerializedCompositeKeyBuilder.setCurrentKey -> serializeKeyGroupAndKey
           ||
           \/
    keySerializer.serialize(key, keyOutView);    
    
    

    最后一步keySerializer.serialize(key, keyOutView)一个Record的key就被写到keyOutView中,也就是说对应的key是从每个record中获取的,所以在backend.db.put方法中就能获取到对应的Key

其他

对于keyedStateStore是在哪里初始化的,可以看AbstractStreamOperator中initializeState方法:

final StreamOperatorStateContext context =
             streamTaskStateManager.streamOperatorStateContext(
                     getOperatorID(),
                     getClass().getSimpleName(),
                     getProcessingTimeService(),
                     this,
                     keySerializer,
                     streamTaskCloseableRegistry,
                     metrics,
                     config.getManagedMemoryFractionOperatorUseCaseOfSlot(
                             ManagedMemoryUseCase.STATE_BACKEND,
                             runtimeContext.getTaskManagerRuntimeInfo().getConfiguration(),
                             runtimeContext.getUserCodeClassLoader()),
                     isUsingCustomRawKeyedState());

stateHandler =
        new StreamOperatorStateHandler(
                context, getExecutionConfig(), streamTaskCloseableRegistry);

这个方法里也包括了keyedStatedBackend和operatorStateBackend等初始化, 具体的细节后续再解析。

Flink - RocksDBStateBackend 如果要考虑易用性和效率,使用rocksDB来替代普通内存的kv是有必要的 有了rocksdb,可以range查询,可以支持columnfamily,可以各种压缩 但是rocksdb本身是一个库,是跑在RocksDBStateBackend中的 所以taskmanager挂掉后,数据还是没了, 所以RocksDBStateBackend仍然需要类似HDFS这样的分布式存储来存储snapshot kv state需要由rockdb来管理,这是和内存或file backend最大的不同 Abs. 阅读详情

相关推荐

【Flink】SinkUpsertMaterializer:乱序Changelog的终结者与状态管理实战

本文深入解析Flink中的SinkUpsertMaterializer算子,探讨其如何解决分布式环境下Changelog乱序问题,确保数据一致性。通过状态管理机制和优化技巧,该算子能有效处理INSERT、UPDATE和DELETE事件,适用于CDC数据同步、流式数仓ETL等场景。文章还提供了生产环境配置指南和性能调优建议,帮助开发者充分发挥其价值。

weixin_29053073的博客 185

Flink的KeyedStateStore的5中state

KeyedStateStore有ValueState,ListState,ReducingState,AggregatingState,MapState5中状态。下面实现这5种状态示例。 1.KeyedStateStore接口的所有get方法 2.ValueState DataStream<MyType> stream = ...; KeyedStream<MyType...

weixin_42412645的博客 818

基于555定时器的呼吸灯电路

呼吸灯是指LED灯在芯片的控制下完成由亮到暗的逐渐变化,感觉就像人在呼吸,其广泛使用在手机上,起到一个通知提醒的作用。呼吸灯在许多灯光装饰上也有大量使用,如音响、汽车广告牌等,在生活中较为常见。...

qq1074237849的博客 9492

【Flink 面试指南】Flink 详解(三):核心篇 Ⅱ(状态 State)

使用嵌入式的本地数据库 RocksDB 将流计算数据状态存储在本地磁盘中,不会受限于 TaskManager 的内存大小,在执行检查点的时候,再将整个 RocksDB 中保存的 State 数据全量或者增量持久化到配置的文件系统中,在 JobManager 内存中会存储少量的检查点元数据。除了对 State 中数据的访问之外,还提供内部运行时信息,如 State 中数据的序列化器,命名空间(namespace)、命名空间的序列化器、命名空间合并的接口。个独立的线程,将自身的状态写入分布式存储可靠存储中。

Data · Model · Agent · Repeat 2501

AirSim安装和地图加载

详细教程如何安装AirSim并加载地图

fegxg的博客 3033

k8s 查看cpu使用率最高的pod

在 Kubernetes 中,可以使用命令查看 Pod 的资源使用情况,从而找到 CPU 使用率最高的 Pod。

u010674101的专栏 3344

Flink(十二)—— Flink 流计算编程Session Window

1、简介 流处理在实际生产中体现的价值越来越大,Apache Flink这个纯流式计算框架也正在被越来越多的公司所关注并尝试使用其流上的功能。 在2017年波兰华沙大数据峰会上,有一家叫做GetInData的公司,分享了一个关于他们内部如何使用Flink的session window的例子,并因此获评最佳演讲。PPT:STREAMING ANALYTICS BETTER THAN CLASSIC BATCH – WHEN AND WHY ? 基于此演讲,该公司后续写了一个系列blog(2篇),详细的阐

weixin_42073629的博客 581

PX4飞控CAN总线通信深度配置:从menuconfig到驱动加载的完整指南

本文详细解析了PX4飞控中CAN总线通信的深度配置流程,从menuconfig选项设置到驱动加载的完整指南。涵盖硬件抽象层、驱动层和应用层的配置细节,提供实际验证方法和故障排查技巧,帮助开发者高效实现CAN通信,特别适用于无人机和机器人底盘运动控制等场景。

weixin_30374009的博客 499

Flink KeyedProcessFunction为什么能为每个key定义State和Timer?

当调用getRuntimeContext().getState()时,底层会基于当前Key创建专属状态实例,实现多Key共享算子实例但状态隔离。定时器同样通过InternalTimerService与Key绑定,触发时会自动设置对应Key的上下文。具体实现上:定时器注册时将Key编码到TimerHeapInternalTimer,触发时通过keyContext.setCurrentKey还原Key上下文;处理元素时,StreamTaskNetworkOutput会在处理每条数据时前设置Key。

lifallen的博客 3017

好书分享:Control and Estimation with MATLAB(5th Edition)pdf

基于MATLAB的控制与估计》(第5版)由八章组成,包括控制算法和设计。主要内容包括状态估计和数据平滑、RLS和卡尔曼滤波器状态估计、控制系统设计、自适应控制和PID。书中的概念已经使用MATLAB和Simulink实现。提供了可下载的MATLAB和Simulink文件。适合人群:大学生、研究生、控制类工程研究人员。需要电子版pdf,回复索取。

jixianhu的博客 1510

自动驾驶仿真:基于Carsim开发的加速度请求模型

1、自动驾驶行业中,算法端对于纵向控制的功能预留接口基本都是加速度,我们需要给控制器仿真加速度的信号,控制器才会实现对纵向功能的控制。2、Carsim或者其他动力学软件,主要提供者节气门开度和主缸压力进行控制。我们在进行联合仿真时,往往都要通过PID的方式将请求加速度转换成对应的节气门开度与主缸压力传给动力学软件进行闭环控制。

zataji的博客 6914

Flink State状态管理

State概述 Keyed State和Operator State Flink中的状态分为两类,Keyed State和Operator State。Keyed State是和具体的Key相绑定的,只能在KeyedStream上的函数和算子中使用。Opeartor State则是和Operator的一个特定的并行实例相绑定的,例如Kafka Connector中,每一个并行的Kafka Consumer都在Operator State中维护当前Consumer订阅的partiton和offset。由于

METON的博客 1483

YOLOv8实战教程:从模型训练到改进的全流程指南

回顾这段YOLOv8的实战历程,从最初的模型训练到后来的各种改进尝试,我深刻体会到目标检测技术的魅力与挑战。YOLOv8作为一款优秀的框架,不仅易用性强,而且具备很强的可扩展性,让我能在其基础上不断创新。未来,我计划在以下几个方向继续探索:一是将YOLOv8与多模态技术结合,尝试实现图像与文本的联合目标检测;二是深入研究自监督学习在YOLOv8中的应用,减少对标注数据的依赖;三是探索YOLOv8在更广泛场景的部署,如机器人、自动驾驶等。

LXY_LOVE36的博客 279

flink 对齐与非对齐,窗口,状态state原理详解

‌‌ 适用于需要精确控制处理时间和不希望有重叠数据的场景。‌‌ 适用于需要处理重叠数据以捕捉更复杂模式或趋势的场景。选择合适的窗口类型取决于你的具体需求,比如是否需要处理重叠数据,以及你的应用对延迟的容忍度等。在Flink中灵活使用这些窗口类型可以有效地处理各种流数据问题。

abcy071213的博客 226

从 SM59 到 SPROXY,打通 ABAP 后端与 ES Repository 的代理生成链路

本文探讨了在SAP PI/PO项目中配置ABAP后端系统与ES Repository连接的关键步骤,重点解决ABAP Proxy生成时无法获取接口模型的问题。文章指出: 该配置本质是建立设计时通道,使ABAP系统能通过SPROXY访问ES Repository中的接口模型并生成代理类 配置核心是在SM59创建名为SAP_PROXY_ESR的HTTP连接(类型G),需确保: 目标路径为/rep 使用具备SAP_XI_IS_SERV_USER角色的服务账号 连接测试通过后仍需在SPROXY中验证完整功能 常见陷

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 57

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

PyFlink DataStream 有状态流处理实战:ValueState 状态访问与 State TTL 配置全解析

本文围绕 Apache Flink 官方 PyFlink 示例中的状态访问范例([flink-python/docs/examples/datastream/state.rst](https://link.gitcode.com/i/7436624a2f163381fa7d2d55a4414da3))展开,该文档通过 `literalinclude` 指令直接嵌入并展示可运行示例 [state_a

gitblog_01044的博客 425

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

理解Flink中的状态实现

state的层次结构 keyedState => windowState OperatorState => kafkaOffset stateBackend snapshot/restore internalTimerService RocksDB操作的初探 state ttL state local recovery QueryableState increame...

dingxl555的专栏 1074

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

解析创建KeyedState流程源码

由于在(StreamTask反射)beforeInvoke的“状态初始化”阶段已经把StateInitializationContext(保存了可以创建xxxState的xxxStateStore)交给了StreamOperator的自定义RichFunction,并且AbstractStreamOperator也已经通过成员变量的方式“持有”了KeyedStateStore。各种类型的State则为StateFactory#createState()提供了各自的实现逻辑,此时,

墨玉浮白的博客 511

Flink DataStream 窗口(Windows)完全指南:Window Assigner、Trigger、Evictor 与迟到数据处理

窗口(Window)是 Flink 处理**无界流**的关键机制:它将无限的数据流切分为大小有限的"桶"(bucket),再对每个桶执行聚合或自定义计算。本文以 Flink DataStream API 为对象,系统讲解窗口操作的基本结构、窗口生命周期、四种内置 Window Assigner(滚动/滑动/会话/全局窗口)、三类窗口函数、Trigger 触发机制、Evictor 数据驱逐、Allo

gitblog_00128的博客 798

Jasna 模型选择与配置指南:5 层修复模型如何按显卡与素材搭出最优组合

Jasna 是一款视频马赛克修复工具,一次任务里其实有多个模型在配合干活:一个负责找到马赛克,一个负责把马赛克重绘出来,一个负责把修好的小图放大变清晰,还有一个只服务静态图片。本文回答一个问题——**在你的显卡、素材类型和时间里,这五层模型该怎么组合**,权重文件又该放在哪里。 先记住一条主线:视频走「检测 → 主修复 →(可选)二次修复」,图片直接走 SD 1.5 旁路。 ## 先看装配线:

gitblog_00667的博客 1047

Flink 流式分析:事件时间、Watermark 与窗口计算实战指南

本文基于 Flink 学习指南中的《流式分析》章节,系统讲解在无界数据流上构建可重现、低延迟流式分析应用的两大核心武器:**事件时间(Event Time)与 Watermark**,以及**窗口(Window)计算**。你将掌握如何为乱序数据流配置时间戳提取与 Watermark 生成、如何选择滚动/滑动/会话窗口并配合窗口函数完成聚合、如何用侧输出与允许延迟处理晚到事件,并结合当前仓库源码理解

gitblog_01047的博客 435

Flink DataStream 窗口(Windows)完全指南:Assigner、触发器、驱逐器与迟到数据处理

窗口(Window)是 Flink 处理无限数据流的核心机制,它将无界的流切分成有限大小的"桶"(bucket),从而允许在桶上执行聚合、统计等有界计算。本文以 Flink DataStream API 为主线,完整讲解窗口生命周期、Keyed/Non-Keyed 窗口的区别、四种内置窗口分配器(Tumbling / Sliding / Session / Global)、三类窗口函数(`Redu

gitblog_00936的博客 481

PyFlink DataStream Functions 完全指南:RuntimeContext 与全部用户自定义函数详解

本文围绕 PyFlink 的 `pyflink.datastream.functions` 模块展开,系统梳理 DataStream API 中全部用户自定义函数(UDF)的类型体系、方法签名、上下文语义与使用要点。读完本文,你将能够基于 PyFlink 正确实现 Map/FlatMap/Reduce/Aggregate/Process/Window/Broadcast 等各类函数,并理解 `Ru

gitblog_00698的博客 161

Flink – WindowedStream

在WindowedStream上可以执行,如reduce,aggregate,min,max等操作 关键是要理解windowOperator对KVState的运用,因为window是用它来存储window buffer的 采用不同的KVState,会有不同的效果,如ReduceState,ListState   Reduce   /** * Applies the g...

weixin_33716941的博客 665

关于使用Flink RocksDB状态后端时一定要写MapState而非ValueState<Map>这档事(以及解决方法)...

前言 抱歉起这种烂大街的日本轻小说风格标题来吸引注意力。原本我认为这是常识,不需要专门写一篇文章来讲解如此细碎的点。但是在最近工作巡检中发现了越来越多如同ValueState<Map>的状态用法(当然大部分是历史遗留),部分Flink作业深受性能问题困扰,所以还是抽出点时间快速聊一聊,顺便给出不算优雅但还算有效的挽救方案。 基于RocksDB的状态序列化 我们已经知道,RocksDB是...

LittleMagic's Blog 435

FLink之StreamOperator

AbstractStreamOperator作为StreamOperator的基本实现类,所有的Operator都会继承和实现该抽象方法用于存储KeyedState的状态管理后端,默认为HashMapStateBackend。如果配置RocksDB作为状态存储后端,则此处为RocksDBKeyedStateBackend。

m0_43437171的博客 1719
上一篇: Spark中python和jvm的通信杂谈--ArrowConverter
下一篇: Spark 3.4.x Server Client模式下的数据传输实现
鸿乃江边鸟
博客等级 码龄6年 3746粉丝 235原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值