Flink -- Keyed State
/* <pre>{@code
* DataStream<MyType> stream = ...;
* KeyedStream<MyType> keyedStream = stream.keyBy("id");
*
* keyedStream.map(new RichMapFunction<MyType, Tuple2<MyType, Long>>() {
*
* private ValueState<Long> count;
*
* public void open(Configuration cfg) {
* state = getRuntimeContext().getState(
* new ValueStateDescriptor<Long>("count", LongSerializer.INSTANCE, 0L));
* }
*
* public Tuple2<MyType, Long> map(MyType value) {
* long count = state.value() + 1;
* state.update(value);
* return new Tuple2<>(value, count);
* }
* });
* }</pre>
*/
在使用keyed state时,首先需要初始化,这里以ValueState为例子,
state = getRuntimeContext().getState(new ValueStateDescriptor<Long>("count", LongSerializer.INSTANCE, 0L));
1. 每个state需要一个标识,ValueStateDescriptor,包含唯一名字,Class,和default值
public ValueStateDescriptor(String name, Class<T> typeClass, T defaultValue)
2. getState,向stateBackend注册keyed state,
StreamingRuntimeContext
public <T> ValueState<T> getState(ValueStateDescriptor<T> stateProperties) {
KeyedStateStore keyedStateStore = checkPreconditionsAndGetKeyedStateStore(stateProperties);
stateProperties.initializeSerializerUnlessSet(getExecutionConfig());
return keyedStateStore.getState(stateProperties);
}
调用keyedStateStore.getState(stateProperties)
KeyedStateStore其实就是KeyedStateBackend的封装
public class DefaultKeyedStateStore implements KeyedStateStore { private final KeyedStateBackend<?> keyedStateBackend;
private final ExecutionConfig executionConfig; @Override
public <T> ValueState<T> getState(ValueStateDescriptor<T> stateProperties) {
try {
stateProperties.initializeSerializerUnlessSet(executionConfig);
return getPartitionedState(stateProperties);
} catch (Exception e) {
throw new RuntimeException("Error while getting state", e);
}
}
最终是调用到,keyedStateBackend
private <S extends State> S getPartitionedState(StateDescriptor<S, ?> stateDescriptor) throws Exception {
return keyedStateBackend.getPartitionedState(
VoidNamespace.INSTANCE,
VoidNamespaceSerializer.INSTANCE,
stateDescriptor);
}
AbstractKeyedStateBackend
public <N, S extends State> S getPartitionedState(
final N namespace,
final TypeSerializer<N> namespaceSerializer,
final StateDescriptor<S, ?> stateDescriptor) throws Exception { final S state = getOrCreateKeyedState(namespaceSerializer, stateDescriptor);
final InternalKvState<N> kvState = (InternalKvState<N>) state; return state;
}
getOrCreateKeyedState
public <N, S extends State, V> S getOrCreateKeyedState(
final TypeSerializer<N> namespaceSerializer,
StateDescriptor<S, V> stateDescriptor) throws Exception { InternalKvState<?> existing = keyValueStatesByName.get(stateDescriptor.getName());
if (existing != null) {
@SuppressWarnings("unchecked")
S typedState = (S) existing;
return typedState; //如果keyValueStatesByName有直接返回
} // create a new blank key/value state
S state = stateDescriptor.bind(new StateBinder() {
@Override
public <T> ValueState<T> createValueState(ValueStateDescriptor<T> stateDesc) throws Exception {
return AbstractKeyedStateBackend.this.createValueState(namespaceSerializer, stateDesc);
}
}); InternalKvState<N> kvState = (InternalKvState<N>) state;
keyValueStatesByName.put(stateDescriptor.getName(), kvState); //把新产生的state注册到keyValueStatesByName
3. ValueState读写,value,update
看下ValueState的定义,
HeapValueState
public class HeapValueState<K, N, V>
extends AbstractHeapState<K, N, V, ValueState<V>, ValueStateDescriptor<V>>
implements InternalValueState<N, V> { /**
* Creates a new key/value state for the given hash map of key/value pairs.
*
* @param stateDesc The state identifier for the state. This contains name
* and can create a default state value.
* @param stateTable The state tab;e to use in this kev/value state. May contain initial state.
*/
public HeapValueState(
ValueStateDescriptor<V> stateDesc,
StateTable<K, N, V> stateTable,
TypeSerializer<K> keySerializer,
TypeSerializer<N> namespaceSerializer) {
super(stateDesc, stateTable, keySerializer, namespaceSerializer);
} @Override
public V value() {
final V result = stateTable.get(currentNamespace); if (result == null) {
return stateDesc.getDefaultValue();
} return result;
} @Override
public void update(V value) { if (value == null) {
clear();
return;
} stateTable.put(currentNamespace, value);
}
}
都是通过StateTable,
CopyOnWriteStateTable
@Override
public S get(N namespace) {
return get(keyContext.getCurrentKey(), namespace);
} @Override
public boolean containsKey(N namespace) {
return containsKey(keyContext.getCurrentKey(), namespace);
} @Override
public void put(N namespace, S state) {
put(keyContext.getCurrentKey(), namespace, state);
}
可以看到value不光是记录一个value,而是记录key,namespace,value的关系
其中key是通过,keyContext.getCurrentKey()去到的
keyContext就是KeyedStateBackend
在StreamInputProcessor.processInput的时候,会通过
streamOperator.setKeyContextElement1(record);
把当前的key设置到KeyedStateBackend
这就是为何,对state的操作都是按key隔离开的
Flink -- Keyed State的更多相关文章
- Flink状态专题:keyed state和Operator state
众所周知,flink是有状态的计算.所以学习flink不可不知状态. 正好最近公司有个需求,要用到flink的状态计算,需求是这样的,收集数据库新增的数据. ...
- Flink之state processor api原理
无论您是在生产环境中运行Apache Flink or还是在过去将Flink评估为计算框架,您都可能会问自己一个问题:如何在Flink保存点中访问,写入或更新状态?不再询问!Apache Flink ...
- 从udaf谈flink的state
1.前言 本文主要基于实践过程中遇到的一系列问题,来详细说明Flink的状态后端是什么样的执行机制,以理解自定义函数应该怎么写比较合理,避免踩坑. 内容是基于Flink SQL的使用,主要说明自定义聚 ...
- Flink之state processor api实践
前不久,Flink社区发布了FLink 1.9版本,在其中包含了一个很重要的新特性,即state processor api,这个框架支持对checkpoint和savepoint进行操作,包括读取. ...
- 「Flink」使用Managed Keyed State实现计数窗口功能
先上代码: public class WordCountKeyedState { public static void main(String[] args) throws Exception { S ...
- Flink - Working with State
All transformations in Flink may look like functions (in the functional processing terminology), but ...
- Managing Large State in Apache Flink®: An Intro to Incremental Checkpointing
January 23, 2018- Apache Flink, Flink Features Stefan Richter and Chris Ward Apache Flink was purpos ...
- Flink学习(三)状态机制于容错机制,State与CheckPoint
摘自Apache官网 一.State的基本概念 什么叫State?搜了一把叫做状态机制.可以用作以下用途.为了保证 at least once, exactly once,Flink引入了State和 ...
- Flink中案例学习--State与CheckPoint理解
1.State概念理解 在Flink中,按照基本类型,对State做了以下两类的划分:Keyed State, Operator State. Keyed State:和Key有关的状态类型,它只能被 ...
随机推荐
- mysql 存储引擎对索引的支持
一.首先给出mysql官方文档给出的不同存储引擎对索引的支持 从上面的图中可以得知,mysql 是支持hash索引的,但支持和不支持又和具体的存储引擎有关系.从图中看到InnoDB是支持Btree索引 ...
- 《CLR via C#》读书笔记 之 泛型
第十二章 泛型 2014-06-15 初始泛型 12.3 泛型基础结构 12.3.1 开放类型与封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码爆炸 12.6 ...
- OpenGL教程一
引自:https://blog.csdn.net/u013654125/article/details/73613644 GLEW, GLFW和GLM介绍 现在你有了工程,就让我们开始介绍下工程所用到 ...
- kafka消费数据策略
单线程消费 以之前生产者中的代码为例,事先准备好了一个 Topic:data-push,3个分区. 先往里边发送 100 条消息,没有自定义路由策略,所以消息会均匀的发往三个分区. 先来谈谈最简单的单 ...
- 5. RAMN备份与恢复
一. rman简介 RMAN(Recovery Manager)是一种用于备份(backup).还原(restore)和恢复(recover)数据库的 Oracle 工具.RMAN只能用于ORACLE ...
- PhoneGap 数据库操作
1,openDatabase phonegap官方文档中已经很清楚的标明,如果使用一个数据库首先要用window对象进行创建: var dbShell = window.openDatabase(na ...
- Xamarin Mono Android实现“再按一次退出程序”
开始研究Android平台软件编程,Xamarin Mono for Android上手快,跨平台共享代码,代价是bug多多,是一味可口的毒药啊! 环境VS2012 + Xamarin Mono An ...
- OpenGL——二维几何变换
平移.旋转.缩放的实现 #include<iostream> #include <math.h> #include<Windows.h> #include < ...
- 延续(continuation)
首先看下延续的定义: 续延是在运行中被暂停了的程序:即含有计算状态的单个函数型对象.当这个对象被求值时,就会在它上次停下来的地方重新启动之前保存下来的计算 在计算机科学和程序设计领域,延续是计算机程序 ...
- inittab 解析
Linux完成内核(Kernel)引导后,会由init初始化进程调用/etc/inittab配置文件(ps -aux | less,init进程号为始终为1,是所有系统进程的起点,init进程也有一个 ...