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有关的状态类型,它只能被 ...
随机推荐
- easy_install与pip 区别
作为Python爱好者,如果不知道easy_install或者pip中的任何一个的话,那么...... easy_insall的作用和perl中的cpan,ruby中的gem类似,都提供了在线一键 ...
- JavaScript反向shell
Node.js反向Shell 摘自:http://www.itfang.net/?p=109 如下的Javascript就是一个Node.js的反向连接shell. 这个payload将会生成一个/b ...
- 前台报错:Uncaught TypeError: Cannot read property '0' of null
错误现象: var div1=mycss[0].style.backgroundColor; //这一行提示360和chrome提示:Uncaught TypeError: Cannot read ...
- 【iCore4 双核心板_ARM】例程十:RTC实时时钟实验——显示时间和日期
实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ RTC_TimeTypeDef sTime; RTC_DateTypeDef sDate; ; ...
- Vue中的computed属性
阅读Vue官网的过程中,对于计算属于与监听器章节的内容有点理解的不清晰:https://cn.vuejs.org/v2/guide/computed.html. 后来上网查询了资料,结合官网的说明,总 ...
- Loadrunner C/S关联函数(LSP)AND(LSSS)使用-案例
LSP就是lrs_save_param()函数 LSSS就是lrs_save_searched_string()函数 一下我们用一个例子去说明他们的使用. C/S机制和B/S不一样,特别是有一个dat ...
- SQL 逗号分隔将一行拆成多行
and number<=len(a.KOrderID) and type=)=',')
- elasticsearch client 为空 错误信息:java.lang.NoSuchMethodError: com.google.common.util.concurrent.MoreExecutors.directExecutor()Ljava/util/concurrent/Executor
错误信息:java.lang.NoSuchMethodError: com.google.common.util.concurrent.MoreExecutors.directExecutor() ...
- 面试之C语言字符串操作总结大全(转载)
趁着十一就好好补补数据结构吧,通信这个不软不硬的专业,现在还是得好好学学补习补习,,你这个非211的本科生!虽然拿到了一个offer,但是觉得时间还有,得继续拼一拼,希望不辜负! 1)字符串操作 st ...
- 阿里云oss上传文件如何支持https?
let client = new OSS.Wrapper({ accessKeyId: res.data.accessKeyId, accessKeySecret: res.data.accessKe ...