flink不同状态后端和RocksDBstatebackend的配置优化

背景:flink提供了不同的状态后端(state backends)来区分状态的存储方式和状态位置,flink状态可以存储在java堆呢村内或者内存之外。我们可以通过状态后端的设置,flink允许应用保持大容量的应用后端。开发者可以在不改变应用逻辑的情况下设置状态后端。

注意:默认情况下flink的状态会保存在tastmanager的内存中,而checkpoint会保存在jobmanager的内存中。

flink的三种状态后端。
1、memorystatebackend
2、fsstatebackend
3、rocksDBstatebackend

注意如果没有配置,则默认使用MemoryStateBackend。

一、menorystatebackend
MemoryStateBackend内部将状态(state)数据作为对象保存在java堆内存中(taskmanger)中,
通过checkpoint机制,MemoryStateBackend将状态(state)进行快照并保存Jobmanager(master)的堆内存中。

MemoryStateBackend可以通过配置来使用异步快照(asynchronous snapshots),通过异步快照可以避免阻塞管道(blocking piplines)目前是默认开启,当然也可以通过MemoryStateBackend的构造函数配置进行关闭:

new nemorystatebackend(MAX_MEM_STATE_SIZE, false)

MemoryStateBackend的限制:
(1)每个独立的状态(state)默认的限制大小为5M,可以通过构造函数来增加容量,
(2)、状态的大小不能超过akka的framesize大小
(3)、(aggregate state )必须放入JobManager的内存。

适用场景:本地调试和flink任务状态数据量较小的场景

二、fsstatebackend

FsStateBackend通过配置文件系统路径(type, address, path)来进行设置,例如:“hdfs://namenode:40010/flink/checkpoints” 或者 “file:///data/flink/checkpoints”.

FsStateBackend 将动态的数据保存到taskmanger的内存中,通过checkpoint机制,将状态快照写入配置好的文件系统或目录中,最小的元数据保存在jobManger的内存中,另外FsStateBackend通过配置一个fileStateThreshold阈值,小于该值时state会存贮到metadata信息中而非文件中。

FsStateBackend默认通过配置来使用异步快照(asynchronous snapshots)避免阻塞管道(blocking pipelines),当然也可以通过FsStateBackend的构造函数配置进行关闭:

new FsStateBackend(path, false);

FsStateBackend适用场景:
1)大状态、长窗口、大key/value状态的的任务
2)全高可用配置

例如
在这里插入图片描述

三、RocksDBStateBackend

RocksDBStateBackend也通过配置文件系统路径来配置,例如:“hdfs://namenode:40010/flink/checkpoints” 或者 “file:///data/flink/checkpoints”

RocksDBStateBackend内部默认会构造一个FsStateBackend来初始化checkpointStreamBackend属性,在实现StateBackend接口的resolveCheckpoint和createCheckpointStorage方法时实际上调用checkpointStreamBackend的相关方法来实现:

@Override
public CompletedCheckpointStorageLocation resolveCheckpoint(String pointer) throws IOException {
return checkpointStreamBackend.resolveCheckpoint(pointer);
}

@Override
public CheckpointStorage createCheckpointStorage(JobID jobId) throws IOException {
return checkpointStreamBackend.createCheckpointStorage(jobId);
}RocksDBStateBackend将工作状态保存在RocksDB数据库(位置在taskManagerd的数据目录)。通过checkpoint, 整个RocksDB数据库被复制到配置的文件系统或目录中。最小元数据保存jobManager的内存中。RocksDBStateBackend可以通过enableIncrementalCheckpointing参数配置是否进行增量Checkpoint(而MemoryStateBackend 和 FsStateBackend不能)。

跟FsStateBackend不同的是,RocksDBStateBackend 仅支持异步快照(asynchronous snapshots)。

适用场景
1)超大状态、长窗口、大key/value状态的的任务
2)全高可用配置
3)最好是对状态读写性能要求不高的作业

注意:由于RocksDBStateBackend 将工作状态存储在taskmanager的本地文件系统中,状态数量仅仅受本地磁盘容量限制,对比于FsStateBackend保存工作状态在内存中,RocksDBStateBackend能避免flink任务持续运行可能导致的状态数量暴增而内存不足的情况,但是吞吐量方面就相比于前两种方面较差。

综述:flink虽然支持多种stateBackend,但是当所需的状态非常大的时候我们只能选择RocksDBStateBackend 可供选择。RocksDB是基于磁盘的KV数据库,由于磁盘是基于B树的LSM树的存储结构。LSM 树读放大问题比较严重,而且当 Flink 任务比较大,且对状态访问比较频繁时,机械硬盘的磁盘 IO 可能成为性能瓶颈。

解决方式一
建议生产环境使用 SSD 作为 RocksDB 的存储介质。但是有些集群可能并没有配置 SSD。此种方式可以大大提升flink读写状态时对磁盘的吞吐量。

解决方式二
建议使用多块硬盘来分担压力,可以通过flink-conf.yaml 中配置 state.backend.rocksdb.localdir 参数来指定 RocksDB 在磁盘中的存储目录。(当一个taskManager包含3个slot时候,单个服务器上的三个并行度对磁盘造成频繁读写,从而导致三个并行度的之间相互争抢同一个磁盘 io,这样必定导致三个并行度的吞吐量都会下降。)
我们可以在flink的 state.backend.rocksdb.localdir 参数可以指定多个目录,一般大数据服务器都会挂载很多块硬盘,我们期望同一个 TaskManager 的三个 slot 使用不同的硬盘从而减少资源竞争。具体参数配置如下所示:

tate.backend.rocksdb.localdir: /data1/flink/rocksdb,/data2/flink/rocksdb,/data3/flink/rocksdb,/data4/flink/rocksdb,/data5/flink/rocksdb,/data6/flink/rocksdb,/data7/flink/rocksdb,/data8/flink/rocksdb,/data9/flink/rocksdb,/data10/flink/rocksdb,/data11/flink/rocksdb,/data12/flink/rocksdb

注:代码方式待调研

解决方式三
磁盘负载均衡策略调整。源码中对数据checkpoint采用了random的策略来分配dir。所以有时会造成多个solt同事读写一个磁盘情况。造成不同磁盘IO读写负载不同。造成性能下降的情况发生。

采用不同负载策略一般包括轮循策略、指定权重策略、Round Robin 策略、最低负载策略、Random 策略等具体不同实想方式参考
https://mp.weixin.qq.com/s/mjWGWJVQ_zSVOgZqtjjoLw

猜你喜欢

转载自blog.csdn.net/weixin_40809627/article/details/107182189