Pebble 性能参数调优
Pebble vs Rocksdb参数调优表
序号 | Pebble参数 | Pebble配置建议 | Rocksdb参数 | Rocksdb配置建议 | 其他 |
---|---|---|---|---|---|
LevelOptions | |||||
1 | BlockRestartInterval | // BlockRestartInterval is the number of keys between restart points for delta encoding of keys. // BlockRestartInterval是键的delta编码的重启点之间的键数量 // 所以什么是delta encoding, 什么又是restart points // The default value is 16. |
不太懂 | ||
2 | BlockSize int | BlockSize是每个表块的未压缩的目标大小,以字节为单位。 // The default value is 4096. |
block-size = "64KB" | 数据块大小。RocksDB 是按照 block 为单元对数据进行压缩的,同时 block 也是缓存在 block-cache中的最小单元(类似其他数据库的 page 概念)。 | 数据块越大 写放大和空间放大越小 读放大越大 |
3 | BlockSizeThreshold int | 如果区块大小大于目标区块大小的指定百分比,并且添加下一个条目会导致区块大于目标区块大小,则BlockSizeThreshold将结束一个区块。 // The default value is 90 | |||
4 | Compression Compression | 压缩定义了要使用的每个块的压缩算法。 The default value (DefaultCompression) uses snappy compression. |
compression-per-level = ["no", "no", "lz4", "lz4", "lz4", "zstd", "zstd"] | # RocksDB 每一层数据的压缩方式,可选的值为:no,snappy,zlib,bzip2,lz4,lz4hc,zstd。它表示 level0 和 level1 不压缩,level2 到 level4 采用 lz4 压缩算法, level5 和 level6 采用 zstd 压缩算法,。 no 表示没有压缩,lz4 是速度和压缩比较为中庸的压缩算法,zlib 的压缩比很高,对存储空间比较友好,但是压缩速度比较慢,压缩的时候需要占用较多的 CPU 资源。不同的机器需要根据 CPU 以及 I/O 资源情况来配置怎样的压缩方式。例如:如果采用的压缩方式为"no:no:lz4:lz4:lz4:zstd:zstd",在大量写入数据的情况下(导数据),发现系统的 I/O 压力很大(使用 iostat 发现 %util 持续 100% 或者使用 top 命令发现 iowait 特别多),而 CPU 的资源还比较充裕,这个时候可以考虑将 level0 和level1 开启压缩,用 CPU 资源换取 I/O 资源。如果采用的压缩方式 为"no:no:lz4:lz4:lz4:zstd:zstd",在大量写入数据的情况下,发现系统的 I/O 压力不大,但是 CPU资源已经吃光了,top -H 发现有大量的 bg 开头的线程(RocksDB 的 compaction 线程)在运行,这个时候可以考虑用 I/O 资源换取 CPU 资源,将压缩方式改成"no:no:no:lz4:lz4:zstd:zstd"。总之,目的是为了最大限度地利用系统的现有资源,使 TiKV 的性能在现有的资源情况下充分发挥。 | 重点关注 |
5 | FilterPolicy | FilterPolicy定义了一种过滤算法(比如Bloom过滤器),可以减少Get调用的磁盘读取。其中一个实现是来自pebble/bloom包的bloom.FilterPolicy(10)。 // The default value means to use no filter. |
重点关注 最起码都有70%的空间压缩率, 而且查询的时间接近O(1),用一定的空间去换取更高效的(CPU节约, 时间节约)查询显然是合算的买卖. |
||
6 | FilterType FilterType | FilterType定义了现有的过滤策略是应用在块级还是表级。块级过滤器在创建时使用的内存较少,但是访问速度较慢,因为必须首先对索引中的键进行检查以找到过滤器块。表级过滤器需要的内存与sstable中键的数量成正比,但在确定键是否存在时避免了索引的查找。除了在内存有限的情况下,表级过滤器应该是首选。 // Table-level filters should be preferred except under constrained memory situations. 但是怎样的情况算是内存受限的情况呢 |
|||
7 | IndexBlockSize int | IndexBlockSize是每个索引块的未压缩的目标大小,单位是字节。当索引块的大小大于这个目标时,两级索引将被自动启用。把这个选项设置成一个大值(比如math.MaxInt32),就会禁止自动创建两级索引。 // The default value is the value of BlockSize. |
|||
8 | TargetFileSize int64 | 当前level的目标文件大小 | |||
Options | |||||
1 L0 compaction相关配置 | L0CompactionFileThreshold int | 触发L0压实所需的L0文件的数量 | |||
1-2 | L0CompactionThreshold int | 触发L0compaction所需的L0 read-amplification。 | level0-slowdown-writes-trigger = 20 | 当 level0 的 sst 文件个数到达 level0-slowdown-writes-trigger 指定的限度的时候 RocksDB 会尝试减慢写入的速度。因为 level0 的 sst 太多会导致 RocksDB 的读放大上升。level0-slowdown-writes-trigger 和 level0-stop-writes-trigger 是 RocksDB 进行流控的另一个表现。当 level0 的 sst 的文件个数到达 4(默认值),level0 的 sst 文件会和 level1 中有 overlap 的 sst 文件进行 compaction,缓解读放大的问题。 | |
1-3 | L0StopWritesThreshold int | 对L0 read-amplification的硬限制,计算为L0子级的数量。当达到这个阈值时,写会被停止。 | level0-stop-writes-trigger = 36 | 当 level0 的 sst 文件个数到达 level0-stop-writes-trigger 指定的限度的时候,RocksDB 会 stall 住新的写入。 | |
2 | LBaseMaxBytes | LBase的最大字节数。基准层LBase是L0被压缩到的层次。基准层LBase是根据LSM中的现有数据动态确定的。其他级别的最大字节数是根据基础级别的最大尺寸动态计算的。当一个级别的最大字节数被超过时,会请求压缩。 | |||
3 | MaxManifestFileSize int64 | MaxManifestFileSize是允许MANIFEST文件的最大尺寸。当MANIFEST文件超过这个大小时,它就会被翻转并创建一个新的MANIFEST。 | max-manifest-file-size = "20MB" | # RocksDB MANIFEST 文件的大小限制更详细的信息请参考:https://github.com/facebook/rocksdb/wiki/MANIFEST | |
4 | MaxOpenFiles | MaxOpenFiles是对DB可以使用的Open File数量的一个软限制。 默认值是1000。 | max-open-files = 40960 | RocksDB 能够打开的最大文件句柄数。 | 将文件句柄都保持打开, 避免昂贵的table cache调用, 那么代价呢? |
5 | MemTableSize int | 稳定状态下的MemTable的大小。实际的MemTable大小从min(256KB, MemTableSize)开始,之后的每一个MemTable都会加倍,直到MemTableSize。这减少了MemTable对短暂的(测试)DB实例造成的内存压力。注意,可以有多个MemTable存在,因为刷新一个MemTable需要在后台创建一个新的MemTable并写入旧的MemTable的内容。MemTableStopWritesThreshold对排队的MemTable的大小做了硬性限制。 | write-buffer-size = "128MB" 官方512M |
# RocksDB memtable 的大小。 | 原来是从256KB进行增加, 一直增加到MemTableSize |
6 | MemTableStopWritesThreshold int | 队列中的MemTable大小的硬限制。当队列中的MemTable大小之和超过MemTableStopWritesThreshold*MemTableSize时,就会停止写入。这个值应该至少是2,否则每当MemTable被刷新时,写操作就会停止。 | max-write-buffer-number = 5 | # 最多允许几个 memtable 存在。写入到 RocksDB 的数据首先会记录到 WAL 日志里面,然后会插入到 memtable 里面,当 memtable 的大小到达了 write-buffer-size 限定的大小的时候,当前的memtable 会变成只读的,然后生成一个新的 memtable 接收新的写入。只读的 memtable 会被RocksDB 的 flush 线程(max-background-flushes 参数能够控制 flush 线程的最大个数) flush 到磁盘,成为 level0 的一个 sst 文件。当 flush 线程忙不过来,导致等待 flush 到磁盘的memtable 的数量到达 max-write-buffer-number 限定的个数的时候,RocksDB 会将新的写入stall 住,stall 是 RocksDB 的一种流控机制。在导数据的时候可以将 max-write-buffer-number的值设置的更大一点,例如 10。 | 不太理解,猜想是2*256k不太理解 |
7 | WALDir string | WALDir 指定 write-ahead logs (WALs) 的存储路径. 如果为空(默认),WALs将被存储在与sstables相同的目录下(即传递给pebble.Open的目录) | wal-dir = "/tmp/tikv/store" | RocksDB write-ahead logs 目录。如果机器上有两块盘,可以将 RocksDB 的数据和 WAL 日志放在不同的盘上,提高 TiKV 的性能。 |
参考资料
非常重要的阅读材料
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!