flink MapState状态

996 阅读1分钟

使用flink状态需要先创建状态的类型描述,flink中的类型信息都使用TypeInformation进行描述,flink使用自定义的类型主要是为了对其存储做一些优化,比如对java类中变量存储的字节对齐的优化,每种TypeInformation类型都提供了对应的序列化器,用于数据在flink中的网络传输或者持久化,比如这里需要将java类型转化为flink中的TypeInformation类型,然后序列化后存储在rocksdb中。

MapStateDescriptor<String, Integer>  indexStateDesc = new MapStateDescriptor<String, Integer>("indexState",
                TypeInformation.of(String.class),
                TypeInformation.of(Integer.class));

然后通过RuntimeContext中创建状态变量,RuntimeContext是AbstractRichFunction中的一个变量,每个AbstractRichFunction都有自己的RuntimeContext。

MapState<String, Integer> mapState = getRuntimeContext().getMapState(indexStateDesc);

使用put进行写入

mapState.put("1",1);

首先会调用UserFacingMapState中的put方法,UserFacingMapState为mapstate的包装类

	@Override
	public void put(K key, V value) throws Exception {
		originalState.put(key, value);
	}
        private final MapState<K, V> originalState;

然后会调用UserFacingMapState中originalState变量的put方法,这里才是实际使用的MapState的具体实现,如HeapMapState或者是RocksDBMapState, MemoryStateBackend和FsStateBackend在不进行checkpoint的时存储方式一样都是使用HeapMapState模式

这里使用的是RocksDBMapState

    public void put(UK userKey, UV userValue) throws IOException, RocksDBException {
        byte[] rawKeyBytes = this.serializeCurrentKeyWithGroupAndNamespacePlusUserKey(userKey, this.userKeySerializer);
        byte[] rawValueBytes = this.serializeValueNullSensitive(userValue, this.userValueSerializer);
        this.backend.db.put(this.columnFamily, this.writeOptions, rawKeyBytes, rawValueBytes);
    }

这里基于CurrentKeyWithGroup和Namespace进行序列化生成RocksDB的key,然后放入rocksdb,

Namespace 用于区分窗口,而KeyGroup是用来对keyby的key进行hash分组,