/* <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. numpy数组(4)-二维数组

    python创建二维 list 的方法是在 list 里存放 list : l = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] numpy可以直接 ...

  2. ES6,扩展运算符的用途

    ES6的扩展运算符可以说是非常使用的,在给多参数函数传参,替代Apply,合并数组,和解构配合进行赋值方面提供了很好的便利性. 扩展运算符就是三个点“...”,就是将实现了Iterator 接口的对象 ...

  3. Java动态代理与反射详解

    首先我得先请大家不要误会,博客园说转载的文章放在文章分类里,原创的文章用随笔写,我开先还以为随笔是拿来写抒情文的(滑稽),后来才发现不是这样的,但是自己所有的文章都在文章分类里了,又懒得搬运,所以我就 ...

  4. 【LINUX】——如何配置宿主机和虚拟机IP在同一网段

    宿主机:win7  10.8.2.50 255.255.255.0 虚拟机:redhat 如果使用 NAT 的网络连接方式,虚拟机的 IP 会被分配为 192.168.*.* 网段,从虚拟机 ping ...

  5. Oracle分析函数-排序排列(rank、dense_rank、row_number、ntile)

    (1)rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名. (2)dense_rank函数返回一个唯一的值, ...

  6. C语言之单元测试

    在ITOO高校云平台项目实践中,我们模板的模块因为在调别人的接口时出现了问题,为了弄明白是不是接口出了问题,就必须学会单元测试. WHAT? 单元测试(unit testing),是指对软件中的最小可 ...

  7. Spark学习笔记——泰坦尼克生还预测

    package kaggle import org.apache.spark.SparkContext import org.apache.spark.SparkConf import org.apa ...

  8. CentOS7 yum方式安装MariaDB 10.2.13-1

    注:以下步骤都是以root身份运行. 一.建立mariadb.repo 1,编辑新文件,命令:vim  /etc/yum.repos.d/mariadb.repo 2,输入如下内容,保存退出 [mar ...

  9. 01简单工厂模式SimpleFactory

    一.什么是简单工厂模式 简单工厂模式属于类的创建型模式,又叫做静态 工厂方法模式.通过专门定义一个类来负责创建 其他类的实例,被创建的实例通常都具有共同的 父类. 二.模式中包含的角色及其职责 1.工 ...

  10. 使用命令行模式启动VMWare虚拟机

    工作中使用到在centos中安装vmware Workstation部署虚拟机,以前都是使用图形界面启动虚拟机,由此要调整VNC的分辨率大小,重启VNC Server后所有虚拟机都关闭了.事后分析可能 ...