跳转至

RocksDB 提供一组选项给用户来决定 IO 应该如何执行

控制写 IO

1 范围 Sync

RocksDB 的数据文件通常通过追加的形式生成。文件系统会选择把写入缓冲起来直到脏页达到一个阈值,然后把所有这些页面都写出。这可能会造成突发写 IO,导致线上的 IO 等待过久,导致高查询延迟。你可以要求 RocksDB 周期性通知 OS 把已经存在的脏页写出,具体做法就是为 SST 文件设置 options.bytes_per_sync,为 WAL 文件设置 options.wal_bytes_per_sync。在底层,每当一个文件到达这个大小的时候,他就会调用 Linux 的 sync_file_range。当前使用的页不会被包含在范围 Sync 中。

2 限流器

你可以通过 options.rate_limiter 控制 RocksDB 的总写文件速率,一次保留足够的 IO 带宽给在线查询。参考 限流器

3 最大写缓冲

往一个文件追加数据的时候,除非声明了需要 fsync,否则 RocksDB 在写入文件系统前会有内部的文件缓冲区。这个缓冲区的最大大小可以通过 options.writable_file_max_buffer_size 来控制。在 直接IO模式 或者在一个没有页缓存的文件系统,可以通过这个参数进行调优。在非直接 IO 模式,加大这个缓冲区的大小仅仅减少了 write 系统调用的次数,并且通常不会改变 IO 行为,所以,除非这个就是你想要的,通常应该把这个值设定为 0 来节省内存

控制读 IO

1 fadvise

当打开一个 SST 文件进行读取,用户设定 options.advise_random_on_open = true(默认).可以决定 RocksDB 是否会使用 FADV_RANDOM 来调用 fadvise。如果值为 false,则打开文件的时候没有 fadvise 会被调用。如果主要的查询是 Get 或者是非常小范围的迭代,把这个选项设置为 true 通常更好,因为预读取在这些场景没什么帮助。另一方面,options.advise_random_on_open = false 通过告知文件系统做底层预读取,通常会有更好的性能。

不幸的是,如果两种情况同时兼而有之,就没有一个好的设定了。有一个正在进行中的项目,希望通过给 RocksDB 内部迭代器设定预读取来解决这个问题。

2 压缩输入

压缩输入比较特别。他们是长的序列化读取,所以使用用户读取选项的 fadvise 选项通常不是特别好。另外,通常,尽管没有保证,压缩输入文件通常会很快被删除。RocksDB 提供多个方式来解决这些问题:

2.1 fadvise 提示

RocksDB 会对任何压缩输入文件根据 options.access_hint_on_compaction_start 调用 fadvise。当一个文件被选为压缩输入的时候,这个可以覆盖随机 fadvise 设定。

2.2 给压缩输入使用不同的文件描述符

如果 options.new_table_reader_for_compaction_inputs = true,RocksDB 会使用不同的文件描述符来打开压缩输入。这可以避免混淆普通数据文件的 fadvise 设定和压缩输入文件的。这个选项的限制是,RocksDB 不会仅仅创建一个新的文件描述符,而是重新读索引,过滤器和其他元数据块,然后把他们存储在内存,这会带来额外的 IO 以及更多的内存使用。

2.3 压缩输入文件的预读取

如果 options.compaction_readahead_size 为 0,你可以自己做预读取。这个选项被设置的时候,options.new_table_reader_for_compaction_inputs 会自动变为 true。这个选项允许用户保持 options.access_hint_on_compaction_start 为 NONE。

如果直接 IO 被打开,或者文件系统不支持预读取,设置这个是不好的。

直接 IO

与上面的通过文件系统控制 IO,你还可以通过 option use_direct_reads 与/或 use_direct_io_for_flush_and_compaction,在 RocksDB 里面打开直接 IO,来直接控制 IO,如果直接 IO 被打开,上面的部分或者全部选项,都可能不生效。更多细节参考 直接IO

内存映射

options.allow_mmap_reads 与 options.allow_mmap_writes 允许 rocksdb 在读取或者写入的时候分别 mmap 整个数据文件,这种做法的好处是可以减少 pried 和 write 的时候的系统调用,并且,在很多情况下,可以减少内存拷贝。如果 DB 运行在 ramfs,options.allow_mmap_reads 通常可以显著提升性能。他们也可以在块设备的文件系统上被使用。然而,根据我们之前的经验,文件系统通常没法做到完美维护这类内存映射,有时候还会导致慢查询。在这种情况下,我们建议你只在必须的情况下,谨慎尝试。