rocksdb写放大_Rocksdb

本文详细介绍了Apache Flink中RocksDB作为状态后端的使用,探讨了RocksDB的内存管理配置,如block_cache_size、write_buffer_size和max_write_buffer_number,以及它们对写放大和读放大的影响。文章还涵盖了RocksDB的数据格式、读写流程、整体架构,并分析了其在实时场景中的适用性和性能特点,如LSM树结构、Compaction策略和读写优化。此外,文章提及RocksDB在分布式事务处理中的角色,包括二阶段提交流程、冲突检测和性能测试。总结了RocksDB的特性,如支持多线程合并和多种压缩算法,以及适用于需要大量状态操作的Flink应用程序。
摘要由CSDN通过智能技术生成

Apache Flink中的RocksDB状态后端

RocksDB 的 compaction 策略,并且提到了读放大、写放大和空间放大的概念,对 RocksDB 的调优本质上就是在这三个因子之间取得平衡。而在 Flink 作业这种注重实时性的场合,则要重点考虑读放大和写放大。

70adaa8c24d53648254cfb199da45bd9.png

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。
    在深入了解配置参数之前,让我们首先重新讨论在flink中如何使用RocksDB来进行状态管理。当您选择RocksDB作为状态后端时,您的状态将被序列化成字节存在堆外内存或本地磁盘中。RocksDB是一个键值存储,它被组织为一个日志结构的合并树(LMS树)。当用于在Flink中存储Keyed状态时,Key由<Keygroup,Key,Namespace>的序列化字节组成,而value由序列化之后的state的字节组成。每次注册keyed状态时,它都会映射到column family(类似于传统数据库中的表),并且键值对将作为序列化字节存储在RocksDB中。这意味着每次READ或WRITE操作都不得不对数据进行序列化/反序列化,

使用RocksDB作为状态后端有许多优点:它不受垃圾回收的影响,与堆中的对象相比,它通常会有较低的内存开销,并且它是目前唯一支持增量检查点的选项。 此外

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值