RocksDB
flink在生产环境中常用RocksDB作为状态后端
1、subtask在taskmanager中作为一个线程运行,如果设置了RocksDB状态后端,RocksDB也会启动一个独立的线程,供subtask来使用。
2、RocksDB是一个kv数据库,因此只能存储flink的键控状态,算子状态还是会放到subtask中。
3、RocksDB会单独占据一块flink内存,它不受JVM GC管控
4、RocksDB会把数据存储到taskmanager所在磁盘上。
5、RocksDB比HashBackend的优点在于,状态数据存储空间大,文件存储更加稳定
使用RocksDB
<!-- RocksDB状态后端使用开始 -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-statebackend-rocksdb_${scala.version}</artifactId>
<version>${flink.version}</version>
</dependency>
// timer优化
Configuration conf = new Configuration();
ConfigOption<String> timer = ConfigOptions.key("state.backend.rocksdb.timer-service.factory").stringType().noDefaultValue();
conf.set(timer, "HEAP");
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(conf);
// 设置rocksdb statebackend,增量模式
// 默认不是增量,会把全量的状态数据保存到hdfs,否则只是同步增连的状态
env.setStateBackend(new EmbeddedRocksDBStateBackend(true));
// 开启checkpoint
env.enableCheckpointing(10000, CheckpointingMode.EXACTLY_ONCE);
// 设置checkpoint的存储路径
env.getCheckpointConfig().setCheckpointStorage("hdfs://hdp01:8020/checkpoints");
RocksDB序列化
rocksdb key value都是基于byte数组进行存储,一个byte数组最大是2^31字节=>2G
如果超过2G会导致状态读取异常。
RocksDB优化
如果使用RocksDB做状态后端,Flink中的定时器(timer-service),也会放到RocksDB中,这样定时器会被频繁访问,导致效率问题,因此可以设置一下,将timer放到heap(内存)上,具体做法见上述代码