前言
RocksDB 是基于LSM的树存储引擎,可调参的有上百个,并且参数之间还有相互的影响,另外根据RUM猜想,读放大、写放大以及空间放大之间是制约关系,生产环境下需在三种放大因子之间进行权衡,这更增加了调优的难度。
架构图
RUM猜想
猜想指的是在 Read Overhead,Update Overhead 和 Memory (or Storage) Overhead 中,同时优化 2 项时需要以剩余的 1 项劣化作为代价
关键指标
调优需要关注的关键指标:
- 磁盘写带宽:Compaction的压力超过磁盘Compaction能力会导致WriteStall, 此时读写都会降低
- 磁盘读IOPS:一般来说IOPS很少,如果发现查看看看Compaction是否繁忙,尽量提高block cache的命中率,减少读SST。另外,有时候这个问题可能是由于读index, filter, 大的data block导致的。
- 磁盘空间占用:一般的原则是先保证性能,后优化空间。
- CPU负载:如果CPU高,大概率是读引起,小概率是Compation引起。许多选项会影响到CPU, 比如Compaction、Compression、Bloom Filter、 Block Size
常见问题
系统指标没有打满,但是rocksDB 性能差
- Compaction 很慢: 并行化 + 分配更多的资源
- 写入慢: 手动Flush + Shard
- 延迟较大:确实是CPU还是IO影响
Write Stall 问题
过多Memtable等待FLUSH
- 限速写入: max_write_buffer_number -1 && memtable > 3
- 禁止写入: memtable > max_write_buffer_number
解决方案
-
增加 max_background_flushes : 增加flush的线程数
-
增加 max_write_buffer_number : 提高 触发WriteStall的阈值
过多的L0文件(L0
文件就是Memtable)
- 限速写入:文件数 > level0_slowdown_writes_trigger
- 禁止写入:文件数 > level0_stop_writes_trigger
解决方案
如果因为过多的L0或者过多的Compaction数据,那么就要减少写放大:
-
增加 max_background_compactions
-
增加 write_buffer_size : memtable更大,降低写放大
-
增加 min_write_buffer_number_to_merge : 写到L0的数据将变少
过多bytes需要Compaction
- 限速写入: write_bytes > soft_pending_compaction_bytes
- 停止写入: write_bytes > hard_pending_compaction_bytes
内存占用
Block Cache相关
RocksDB 的底层存储是2层Block Cache + 系统PageCache, 其实BlockCache 是解压后的数据,而PageCache是原始压缩后的数据, 因此正常情况下减小BlockCache 并不会直接命中磁盘,但是由于PageCache数据需要解压, 所以需要消耗更多的CPU。
Indexes and bloom filters
这里主要是确认Indexes 和 Bloom filter 是否需要常驻内存:
- 如果设置 cache_index_and_filter_blocks 为true, 则把该数据存储在Block Cache 中, 因此数据可以被LRU 换出,可能出现索引未命中cache 的情况
- 如果设置 cache_index_and_filter_blocks 为 false, 则不会放在block Cache中, 读取的文件不关闭会直接放在内存中,随着文件打开越来越多,对应的内存会变得不可控
- 折中方案:设置cache_index_and_filter_blocks=ture && cache_index_and_filter_blocks_with_high_priority 保证在blockCache 的同时 还具有高优先级
Memtable
memtable 一般认为是写入Buffer, 大小由max_buffer_size 限定, 一般来说memtable 越大,写放大越小, 在调整Memtable table 大小的时候,需要同步调整L1 Cache 大小