关于flink:Flink-RocksDB-状态后端参数调优实践

3次阅读

共计 3643 个字符,预计需要花费 10 分钟才能阅读完成。

截至以后,Flink 作业的状态后端依然只有 Memory、FileSystem 和 RocksDB 三种可选,且 RocksDB 是状态数据量较大(GB 到 TB 级别)时的惟一抉择。RocksDB 的性能施展十分仰赖调优,如果全副采纳默认配置,读写性能有可能会很差。

然而,RocksDB 的配置也是极为简单的,可调整的参数多达百个,没有放之四海而皆准的优化计划。如果仅思考 Flink 状态存储这一方面,咱们依然能够总结出一些绝对普适的优化思路。本文先介绍一些基础知识,再列举办法。

Note: 本文的内容是基于咱们在线上运行的 Flink 1.9 版本实际得出的。在 1.10 版本及当前,因为 TaskManager 内存模型重构,RocksDB 内存默认成为了堆外托管内存的一部分,能够免去一些手动调整的麻烦。如果性能依然不佳,须要干涉,则必须将 state.backend.rocksdb.memory.managed 参数设为 false 来禁用 RocksDB 内存托管。

State R/W on RocksDB

RocksDB 作为 Flink 状态后端时的读写逻辑与个别状况略有不同,如下图所示。

Flink 作业中的每一个注册的状态都对应一个列族(column family),即蕴含本人独立的 memtable 和 sstable 汇合。写操作会先将数据写入流动 memtable,写满之后则会转换为不可变 memtable,并 flush 到磁盘中造成 sstable。读操作则会顺次在流动 memtable、不可变 memtable、block cache 和 sstable 中寻找指标数据。另外,sstable 也须要通过 compaction 策略进行合并,最终造成分层的 LSM Tree 存储构造,陈词滥调了。

特地地,因为 Flink 在每个检查点周期都会将 RocksDB 的数据快照长久化到文件系统,所以天然也就不须要再写预写日志(WAL)了,能够平安地敞开 WAL 与 fsync。

之前笔者曾经具体解说过 RocksDB 的 compaction 策略,并且提到了读放大、写放大和空间放大的概念,对 RocksDB 的调优实质上就是在这三个因子之间获得均衡。而在 Flink 作业这种重视实时性的场合,则要重点思考读放大和写放大。

Tuning MemTable

memtable 作为 LSM Tree 体系里的读写缓存,对写性能有较大的影响。以下是一些值得注意的参数。为不便比照,下文都会将 RocksDB 的原始参数名与 Flink 配置中的参数名一并列出,用竖线宰割。

  • write_buffer_size | state.backend.rocksdb.writebuffer.size 单个 memtable 的大小,默认是 64MB。当 memtable 大小达到此阈值时,就会被标记为不可变。一般来讲,适当增大这个参数能够减小写放大带来的影响,但同时会增大 flush 后 L0、L1 层的压力,所以还须要配合批改 compaction 参数,前面再提。
  • max_write_buffer_number | state.backend.rocksdb.writebuffer.count memtable 的最大数量(蕴含沉闷的和不可变的),默认是 2。当全副 memtable 都写满然而 flush 速度较慢时,就会造成写进展,所以如果内存短缺或者应用的是机械硬盘,倡议适当调大这个参数,如 4。
  • min_write_buffer_number_to_merge | state.backend.rocksdb.writebuffer.number-to-merge 在 flush 产生之前被合并的 memtable 最小数量,默认是 1。举个例子,如果此参数设为 2,那么当有至多两个不可变 memtable 时,才有可能触发 flush(亦即如果只有一个不可变 memtable,就会期待)。调大这个值的益处是能够使更多的更改在 flush 前就被合并,升高写放大,但同时又可能减少读放大,因为读取数据时要查看的 memtable 变多了。经测试,该参数设为 2 或 3 绝对较好。

Tuning Block/Block Cache

block 是 sstable 的根本存储单位。block cache 则表演读缓存的角色,采纳 LRU 算法存储最近应用的 block,对读性能有较大的影响。

  • block_size | state.backend.rocksdb.block.blocksize block 的大小,默认值为 4KB。在生产环境中总是会适当调大一些,个别 32KB 比拟适合,对于机械硬盘能够再增大到 128~256KB,充分利用其程序读取能力。然而须要留神,如果 block 大小增大而 block cache 大小不变,那么缓存的 block 数量会缩小,无形中会减少读放大。
  • block_cache_size | state.backend.rocksdb.block.cache-size block cache 的大小,默认为 8MB。由上文所述的读写流程可知,较大的 block cache 能够无效防止热数据的读申请落到 sstable 上,所以若内存余量短缺,倡议设置到 128MB 甚至 256MB,读性能会有非常明显的晋升。

Tuning Compaction

compaction 在所有基于 LSM Tree 的存储引擎中都是开销最大的操作,弄不好的话会非常容易阻塞读写。倡议看官先读读后面那篇对于 RocksDB 的 compaction 策略的文章,获取一些背景常识,这里不再赘述。

  • compaction_style | state.backend.rocksdb.compaction.style compaction 算法,应用默认的 LEVEL(即 leveled compaction)即可,上面的参数也是基于此。
  • target_file_size_base | state.backend.rocksdb.compaction.level.target-file-size-base L1 层单个 sstable 文件的大小阈值,默认值为 64MB。每向上晋升一级,阈值会乘以因子 target_file_size_multiplier(但默认为 1,即每级 sstable 最大都是雷同的)。显然,增大此值能够升高 compaction 的频率,缩小写放大,然而也会造成旧数据无奈及时清理,从而减少读放大。此参数不太容易调整,个别不倡议设为 256MB 以上。
  • max_bytes_for_level_base | state.backend.rocksdb.compaction.level.max-size-level-base L1 层的数据总大小阈值,默认值为 256MB。每向上晋升一级,阈值会乘以因子 max_bytes_for_level_multiplier(默认值为 10)。因为下层的大小阈值都是以它为根底推算出来的,所以要小心调整。倡议设为 target_file_size_base 的倍数,且不能太小,例如 5~10 倍。
  • level_compaction_dynamic_level_bytes | state.backend.rocksdb.compaction.level.use-dynamic-size 这个参数之前讲过。当开启之后,上述阈值的乘法因子会变成除法因子,可能动静调整每层的数据量阈值,使得较多的数据能够落在最高一层,可能缩小空间放大,整个 LSM Tree 的构造也会更稳固。对于机械硬盘的环境,强烈建议开启。

Generic Parameters

  • max_open_files | state.backend.rocksdb.files.open 顾名思义,是 RocksDB 实例可能关上的最大文件数,默认为 -1,示意不限度。因为 sstable 的索引和布隆过滤器默认都会驻留内存,并占用文件描述符,所以如果此值太小,索引和布隆过滤器无奈失常加载,就会重大连累读取性能。
  • max_background_compactions/max_background_flushes | state.backend.rocksdb.thread.num 后盾负责 flush 和 compaction 的最大并发线程数,默认为 1。留神 Flink 将这两个参数合二为一解决(对应 DBOptions.setIncreaseParallelism() 办法),鉴于 flush 和 compaction 都是绝对重的操作,如果 CPU 余量比拟短缺,倡议调大,在咱们的实际中个别设为 4。

结语

除了上述设置参数的办法之外,用户还能够通过实现 ConfigurableRocksDBOptionsFactory 接口,创立 DBOptions 和 ColumnFamilyOptions 实例来传入自定义参数,更加灵便一些。看官可参考 Flink 事后定义好的几个 RocksDB 参数集(位于 PredefinedOptions 枚举中)获取更多信息。

本文转载自 LittleMagic 的博客,原文链接:
https://www.jianshu.com/p/bc7…

正文完
 0