/* <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的更多相关文章

  1. Flink状态专题:keyed state和Operator state

            众所周知,flink是有状态的计算.所以学习flink不可不知状态.         正好最近公司有个需求,要用到flink的状态计算,需求是这样的,收集数据库新增的数据.       ...

  2. Flink之state processor api原理

    无论您是在生产环境中运行Apache Flink or还是在过去将Flink评估为计算框架,您都可能会问自己一个问题:如何在Flink保存点中访问,写入或更新状态?不再询问!Apache Flink ...

  3. 从udaf谈flink的state

    1.前言 本文主要基于实践过程中遇到的一系列问题,来详细说明Flink的状态后端是什么样的执行机制,以理解自定义函数应该怎么写比较合理,避免踩坑. 内容是基于Flink SQL的使用,主要说明自定义聚 ...

  4. Flink之state processor api实践

    前不久,Flink社区发布了FLink 1.9版本,在其中包含了一个很重要的新特性,即state processor api,这个框架支持对checkpoint和savepoint进行操作,包括读取. ...

  5. 「Flink」使用Managed Keyed State实现计数窗口功能

    先上代码: public class WordCountKeyedState { public static void main(String[] args) throws Exception { S ...

  6. Flink - Working with State

    All transformations in Flink may look like functions (in the functional processing terminology), but ...

  7. 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 ...

  8. Flink学习(三)状态机制于容错机制,State与CheckPoint

    摘自Apache官网 一.State的基本概念 什么叫State?搜了一把叫做状态机制.可以用作以下用途.为了保证 at least once, exactly once,Flink引入了State和 ...

  9. Flink中案例学习--State与CheckPoint理解

    1.State概念理解 在Flink中,按照基本类型,对State做了以下两类的划分:Keyed State, Operator State. Keyed State:和Key有关的状态类型,它只能被 ...

随机推荐

  1. easy_install与pip 区别

    作为Python爱好者,如果不知道easy_install或者pip中的任何一个的话,那么......   easy_insall的作用和perl中的cpan,ruby中的gem类似,都提供了在线一键 ...

  2. JavaScript反向shell

    Node.js反向Shell 摘自:http://www.itfang.net/?p=109 如下的Javascript就是一个Node.js的反向连接shell. 这个payload将会生成一个/b ...

  3. 前台报错:Uncaught TypeError: Cannot read property '0' of null

    错误现象: var div1=mycss[0].style.backgroundColor;  //这一行提示360和chrome提示:Uncaught TypeError: Cannot read  ...

  4. 【iCore4 双核心板_ARM】例程十:RTC实时时钟实验——显示时间和日期

    实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ RTC_TimeTypeDef sTime; RTC_DateTypeDef sDate; ; ...

  5. Vue中的computed属性

    阅读Vue官网的过程中,对于计算属于与监听器章节的内容有点理解的不清晰:https://cn.vuejs.org/v2/guide/computed.html. 后来上网查询了资料,结合官网的说明,总 ...

  6. Loadrunner C/S关联函数(LSP)AND(LSSS)使用-案例

    LSP就是lrs_save_param()函数 LSSS就是lrs_save_searched_string()函数 一下我们用一个例子去说明他们的使用. C/S机制和B/S不一样,特别是有一个dat ...

  7. SQL 逗号分隔将一行拆成多行

    and number<=len(a.KOrderID) and type=)=',')

  8. elasticsearch client 为空 错误信息:java.lang.NoSuchMethodError: com.google.common.util.concurrent.MoreExecutors.directExecut‌​or()Ljava/util/concu‌​rrent/Executor

    错误信息:java.lang.NoSuchMethodError: com.google.common.util.concurrent.MoreExecutors.directExecut‌​or() ...

  9. 面试之C语言字符串操作总结大全(转载)

    趁着十一就好好补补数据结构吧,通信这个不软不硬的专业,现在还是得好好学学补习补习,,你这个非211的本科生!虽然拿到了一个offer,但是觉得时间还有,得继续拼一拼,希望不辜负! 1)字符串操作 st ...

  10. 阿里云oss上传文件如何支持https?

    let client = new OSS.Wrapper({ accessKeyId: res.data.accessKeyId, accessKeySecret: res.data.accessKe ...