RocksDB 常见问题

Building RocksDB

问:构建 RocksDB 所需的 gcc 的绝对最低版本是什么?
答:4.8。
问:RocksDB 最新的稳定版本是什么?
答:https://github.com/facebook/rocksdb/releases 中的所有版本都是稳定的。对于 RocksJava,稳定版本在 https://oss.sonatype.org/#nexus-search;quick~rocksdb 中可用。

基本读/写

问:基本操作 Put()、Write()、Get() 和 NewIterator() 线程安全吗?

答:是的。

问:我可以使用多个进程写入 RocksDB 吗?

答:没有。但是,可以使用辅助数据库打开它。如果没有写入数据库,则可以从多个进程以只读模式打开数据库。

问:RocksDB 是否支持多进程读取访问?

答:是的,您可以使用辅助数据库读取它。RocksDB 还可以支持多进程只读进程,而无需写入数据库。这可以通过使用调用打开数据库来完成。DB::OpenAsSecondary()DB::OpenForReadOnly()

问:当另一个线程发出读取、写入或手动压缩请求时关闭 RocksDB 是否安全?

答:没有。RocksDB 的用户在关闭 RocksDB 之前需要确保所有功能都已完成。您可以通过致电来加快等待速度。CancelAllBackgroundWork()

问:支持的最大键和值大小是多少?

答:一般来说,RocksDB 不是为大密钥设计的。键和值的最大建议大小分别为 8MB 和 3GB。

问:将数据加载到 RocksDB 的最快方法是什么?

答:将插入数据定向到数据库的快速方法:

使用单个编写器线程并按排序顺序插入
将数百个密钥批处理到一个写入批处理中
使用矢量记忆表
确保至少为 4options.max_background_flushes
在插入数据之前,请禁用自动压缩,将 和设置为非常大的值。插入所有数据后,发出手动压缩。options.level0_file_num_compaction_triggeroptions.level0_slowdown_writes_triggeroptions.level0_stop_writes_trigger
3-5 将自动完成,如果您调用您的选项Options::PrepareForBulkLoad()

如果可以在插入之前脱机预处理数据。有一种更快的方法:您可以对数据进行排序,并行生成具有非重叠范围的 SST 文件并批量加载 SST 文件。见 https://github.com/facebook/rocksdb/wiki/Creating-and-Ingesting-SST-files

问:删除数据库的正确方法是什么?我可以简单地在实时数据库上调用 DestroyDB() 吗?

答:关闭数据库然后销毁数据库是正确的方法。调用实时数据库是一种未定义的行为。DestroyDB()

问:DestroyDB() 和直接手动删除数据库目录有什么区别?

答:主要区别在于,这将处理 RocksDB 数据库存储在多个目录中的情况。例如,可以通过指定 、 和 的不同路径,将单个数据库配置为将其数据存储在多个目录中。DestroyDB()DBOptions::db_pathsDBOptions::db_log_dirDBOptions::wal_dir

问:有什么更好的方法可以将map-reduce作业生成的键值对转储到RocksDB中吗?

答:更好的方法是使用 SstFileWriter,它允许您直接创建 RocksDB SST 文件并将它们添加到 RocksDB 数据库中。但是,如果要将 SST 文件添加到现有的 RocksDB 数据库,则其键范围不得与数据库重叠。https://github.com/facebook/rocksdb/wiki/Creating-and-Ingesting-SST-files

问:在压缩过滤器回调中读取或写入 RocksDB 是否安全?

答:在压缩过滤器回调中写入 RocksDB 是安全的,但并不总是安全的,因为写入可能会在触发写停止条件时触发死锁。

问:RocksDB 是否保存 SST 文件和内存表作为快照?

答:没有。请参阅 https://github.com/facebook/rocksdb/wiki/RocksDB-Overview#gets-iterators-and-snapshots,了解快照的工作原理。

问:使用 DBWithTTL 时,删除过期密钥是否有时间限制?

答:本身不提供时间上限。过期的密钥在成为任何压缩的一部分时将被删除。但是,不能保证何时开始进行此类压实。例如,如果您有某个从未更新的键范围,则压缩不太可能应用于该键范围。对于分级压缩,您可以使用定期压缩功能强制实施一些限制。该功能现在有一个限制:如果写入速率太慢,以至于永远不会触发内存表刷新,则也不会触发定期压缩。DBwithTTL

问:如果我删除了列系列,但尚未删除列系列句柄,是否仍可以使用它来访问数据?

答:是的。 仅将指定的列族标记为已删除,并且在其引用计数变为零并标记为已删除之前不会删除该列系列。DropColumnFamily()

问:为什么 RocksDB 只发出写入请求时会发出磁盘读取问题?

答:此类 IO 读取来自压缩。RocksDB 压缩从一个或多个 SST 文件中读取,执行类似合并排序的操作,生成新的 SST 文件,并删除它输入的旧 SST 文件。

问:block_size是在压缩之前还是之后?

答:block_size用于压缩前的尺寸。

问:使用options.prefix_extractor后,我有时会看到错误的结果。怎么了?

答:中存在限制。如果使用前缀迭代,则不支持 或 ,许多操作也不支持。一个常见的错误是通过调用 来查找前缀的最后一个键,后跟 。但是,这不受支持。目前无法找到前缀迭代的前缀的最后一个键。此外,在完成所需的前缀后,您无法继续迭代键。在需要这些操作的地方,您可以尝试设置为禁用前缀迭代。options.prefix_extractorPrev()SeekToLast()SeekToFirst()Seek()Prev()ReadOptions.total_order_seek = true

问:如果使用 WriteOptions.sync=true 调用 Put() 或 Write(),是否意味着所有以前的写入也是持久的?

答:是的,但仅适用于以前使用 .WriteOptions.disableWAL=false

问:我禁用了预写日志并依靠 DB::Flush() 来保存数据。它适用于单身家庭。如果我有多个色谱柱系列,我可以做同样的事情吗?

答:是的。设置为跨多个列族启用原子刷新。option.atomic_flush=true

问:删除一系列键的最佳方法是什么?

答:请参阅 https://github.com/facebook/rocksdb/wiki/DeleteRange。

问:色谱柱系列的用途是什么?

答:使用列族的最常见原因:

在数据的不同部分使用不同的压缩设置、比较器、压缩类型、合并运算符或压缩过滤器
删除列族以删除其数据
一个列系列用于存储元数据,另一个列系列用于存储数据。
问:将数据存储在多列族和多 rocksdb 数据库中有什么区别?

答:主要区别在于备份、原子写入和写入性能。使用多个数据库的优点:数据库是备份或检查点的单元。将数据库复制到其他主机比将列系列更容易。使用多个色谱柱系列的优点:

写入批处理跨一个数据库上的多个列系列是原子的。使用多个 RocksDB 数据库无法实现此目的
如果向 WAL 发出同步写入,则数据库过多可能会损害性能。
问:RocksDB 在读取中真的“无锁”吗?

答:在以下情况下,读取可能会持有互斥锁:

访问分片块缓存
在以下情况下访问表缓存options.max_open_files != -1
如果在刷新或压缩完成后立即发生读取,则可能会短暂保留全局互斥锁以获取 LSM 树的最新元数据。
RocksDB所依赖的内存分配器(例如jemalloc)有时可能会持有锁。这些锁仅很少或以细粒度持有。
问:如果我更新多个密钥,我应该发出多个 Put(),还是将它们放在一个写入批处理中并发出 Write()?

答:使用批处理多个键通常比单个键性能更好。WriteBatch()Put()

问:迭代所有密钥的最佳做法是什么?

答:如果是小型或只读数据库,只需创建一个迭代器并迭代所有密钥。否则,请考虑每隔一段时间重新创建一次迭代器,因为迭代器将保留所有资源不被释放。如果需要从一致视图读取,请创建快照并使用它进行迭代。

问:我有不同的密钥空间。我应该使用前缀分隔它们,还是使用不同的列系列?

答:如果每个键空间都相当大,最好将它们放在不同的列系列中。如果可以很小,那么应该考虑将多个键空间打包到一个列族中,以避免维护太多列族的麻烦。

问:迭代器 Next() 的性能是否与 Prev() 相同?

答:反向迭代的性能通常比正向迭代差得多。造成这种情况的原因有很多:

数据块中的增量编码更友好Next()
内存表中使用的跳过列表是单向的,另一个二叉搜索也是如此Prev()
内部键顺序针对 进行了优化。Next()
问:如果我想从 RocksDB 检索 10 个密钥,是将它们批处理并使用 MultiGet() 比发出 10 个单独的 Get() 调用更好吗?

答:使用 有潜在的性能优势。请参阅 https://github.com/facebook/rocksdb/wiki/MultiGet-Performance 。MultiGet()

问:如果我有多个列族,并且在没有列族句柄的情况下调用数据库函数,结果会是什么?

答:它将仅操作默认列系列。

问:我可以跨多个线程重用 ReadOptions、WriteOptions 等吗?

答:只要它们是恒定的,您就可以自由地重复使用它们。

功能支持

问:我可以取消特定的压缩吗?

答:不可以,您不能取消一个特定的压缩。

问:是否可以在进行手动压缩时关闭数据库?

答:不,这样做不安全。但是,您可以调用另一个线程来中止正在运行的压缩,以便您可以更快地关闭数据库。从 6.5 开始,您还可以使用 .CancelAllBackgroundWork(db, true)DB::DisableManualCompaction()

问:直接复制打开的 RocksDB 实例是否安全?

答:不会,除非 RocksDB 实例以只读模式打开。

问:RocksDB 是否支持复制?

答:不可以,RocksDB 不直接支持复制。但是,它提供了一些 API,可用作支持复制的构建基块。例如,允许开发人员迭代自特定时间点以来的所有更新。 见 https://github.com/facebook/rocksdb/wiki/Replication-HelpersGetUpdatesSince()

问:RocksDB 是否支持组提交?

答:是的。多个线程发出的多个写入请求可以组合在一起。其中一个线程在单个写入请求中为这些写入请求写入 WAL 日志,如果配置了一次 fsync。

问:是否可以仅扫描/迭代密钥?如果是这样,这比加载键和值更有效吗?

答:不,它通常不是更有效率。RocksDB 的值通常与键内联存储。当用户循环访问键时,值已加载到内存中,因此跳过该值不会节省太多。在 BlobDB 中,键和大值是分开存储的,因此仅迭代键可能是有益的,但尚不支持。我们将来可能会添加支持。

问:事务对象是否线程安全?

答:不,不是。不能同时向同一事务发出多个操作。(当然,您可以并行执行多个事务,这是该功能的重点。

问:迭代器离开键/值后,这些键/值所指向的内存是否仍保留?

答:不可以,它们可以被释放,除非您设置并且您的设置支持此功能。ReadOptions.pin_data = true

问:是否可以以编程方式从 SST 文件中读取数据?

答:我们现在不支持。但是您可以使用 转储数据。从版本 6.5 开始,您将能够使用 SstFileReader 执行此操作。sst_dump

问:RocksDB 修复:我什么时候可以使用?最佳实践?

答:检查 https://github.com/facebook/rocksdb/wiki/RocksDB-Repairer

配置和调整

问:块缓存的默认值是多少?

答:8MB。对于大多数用例来说,这太低了,因此您可能需要设置自己的值。

问:SST 文件的布隆过滤器块是否总是加载到内存中,或者是否可以从磁盘加载?

答:行为是可配置的。设置为 true 时,仅当发出相关请求时,布隆过滤器和索引块才会加载到 LRU 缓存中。在另一种情况下,设置为 false,则 RocksDB 将尝试将索引块和布隆过滤器保留在内存中,最多保留数量的 SST 文件。BlockBaseTableOptions::cache_index_and_filter_blocksGet()cache_index_and_filter_blocksDBOptions::max_open_files

问:为不同的列系列配置不同的前缀提取器是否安全?

答:是的。

问:我可以更改前缀提取器吗?

答:没有。指定前缀提取器后,无法更改它。但是,您可以通过指定空值来禁用它。

问:如何配置 RocksDB 使用多个磁盘?

答:您可以在多个磁盘上创建单个文件系统(ext3、xfs 等)。然后,您可以在该单个文件系统上运行 RocksDB。 使用磁盘时的一些提示:

如果使用 RAID,请使用较大的 RAID 条带大小(64kb 太小,1MB 会很好)。
请考虑通过指定至少 2MB 来启用预读压缩。ColumnFamilyOptions::compaction_readahead_size
如果工作负载写入量大,请有足够的压缩线程来保持磁盘繁忙
考虑为压缩启用异步写后操作
问:是否可以使用不同的压缩类型打开 RocksDB 并仍读取旧数据?

答:是的,由于 RocksDB 将压缩信息存储在每个 SST 文件中并相应地执行解压缩,因此您可以更改压缩,并且数据库仍然能够读取现有文件。此外,还可以通过指定 来为最后一个级别指定不同的压缩。ColumnFamilyOptions::bottommost_compression

问:我可以将日志文件和 sst 文件放在不同的目录中吗?信息日志怎么样?

答:是的。WAL文件可以通过指定将WAL文件放置在单独的目录中,信息日志也可以通过使用写入单独的目录中。DBOptions::wal_dirDBOptions::db_log_dir

问:如果我使用非默认比较器或合并运算符,我还能使用 ldb 工具吗?

答:在这种情况下,您不能使用常规工具。但是,您可以通过使用此函数传递自己的选项来构建自定义工具并进行编译。ldbldbrocksdb::LDBTool::Run(argc, argv, options)

问:如果我使用不同的压缩样式打开 RocksDB,会发生什么情况?

答:打开具有不同压缩样式或压缩设置的 RocksDB 数据库时,将发生以下情况之一:

如果新配置与当前 LSM 布局不兼容,数据库将拒绝打开。
如果新配置与当前的 LSM 布局兼容,则 RocksDB 将继续并打开数据库。但是,为了使新选项完全生效,可能需要完全压缩。
考虑使用迁移帮助程序函数,如果需要,它将压缩文件以满足新的压缩样式。OptionChangeMigration()

问:RocksDB 有列吗?如果没有列,为什么会有列族?

答:不,RocksDB 没有列。请参阅 https://github.com/facebook/rocksdb/wiki/Column-Families,了解什么是列族。

问:如果我发出完全手动压缩,如何估计可以回收的空间?

答:没有简单的方法可以准确预测它,尤其是在有压实过滤器的情况下。如果数据库大小稳定,则数据库属性是最佳估计值。rocksdb.estimate-live-data-size

问:快照、检查点和备份之间有什么区别?

答:快照是一个合乎逻辑的概念。用户可以使用程序接口查询数据,但底层压缩仍会重写现有文件。

检查点将使用相同的 创建所有数据库文件的物理镜像。如果文件系统硬链接可用于创建镜像文件,则此操作非常便宜。Env

备份可以将物理数据库文件移动到另一个(如 HDFS)。备份引擎还支持不同备份之间的增量复制。Env

问:我应该使用哪种压缩类型?

答:从 LZ4(或 Snappy,如果 LZ4 不可用)开始,适用于所有级别以获得良好的性能。如果要进一步减小数据大小,请尝试在最底层使用 ZStandard(或 Zlib,如果 ZStandard 不可用)。见 https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning#compression

问:如果未删除或覆盖任何密钥,是否需要压缩?

答:即使不需要清除过时的数据,也需要压缩以确保读取性能。

问:在以下选项.disableWAL=true写入后,我使用options.sync=true写入另一条记录,它是否也会保留上一次写入?

答:没有。程序崩溃后,如果写入 using 未刷新到 SST 文件,则写入将丢失。option.disableWAL=true

问:options.target_file_size_multiplier有什么用?

答:这是一个很少使用的功能。例如,您可以使用它来减少 SST 文件的数量。

问:我观察到突发写入 I/O。我怎样才能消除它?

答:尝试使用速率限制器:请参阅 https://github.com/facebook/rocksdb/wiki/Rate-Limiter

问:是否可以在不重新打开数据库的情况下更改压缩过滤器?

答:不支持。但是,您可以通过实现返回不同的压缩过滤器来实现它。CompactionFilterFactory

问:单个数据库可以支持多少个列系列?

答:用户应该能够运行至少数千个列系列,而不会看到任何错误。但是,太多的色谱柱系列通常表现不佳。我们不建议用户使用超过几百个列系列。

问:是否可以重复使用 DBOptions 或 ColumnFamilyOptions 来打开多个数据库或列系列?

答:是的。在内部,RocksDB 总是复制这些选项,因此您可以自由更改它们并重用这些对象

可移植性

问:我可以运行 RocksDB 并将数据存储在 HDFS 上吗?

答:是的,通过使用 返回的 Env,RocksDB 会将数据存储在 HDFS 上。但是,HDFS Env 目前不支持文件锁定。NewHdfsEnv()

问:RocksJava 是否支持所有功能?

答:我们正在努力使 RocksJava 功能兼容。但是,如果您发现缺少某些内容,非常欢迎您提交拉取请求

备份

问:是否可以保留 RocksDB 的“快照”,然后回滚数据库状态?

答:是的,通过备份引擎或检查点。

问:BackupableDB 是否会创建数据库的时间点快照?

答:是的,何时或何时致电。BackupOptions::backup_log_files = trueflush_before_backup = trueCreateNewBackup()

问:备份过程是否会影响对数据库的访问?

答:不可以,您可以同时继续读取和写入数据库。

问:如何配置 RocksDB 以备份到 HDFS?

答:使用并设置backup_env返回值 。BackupableDBNewHdfsEnv()

故障恢复

问:如果我的进程崩溃,是否会损坏数据库?

答:否,但如果禁用预写日志 (WAL),则未刷新的内存表中的数据可能会丢失。

问:如果我的机器崩溃并重新启动,RocksDB 会保留数据吗?

答:当您发出同步写入(写入方式)、调用 或刷新内存表时,将同步数据。WriteOptions.sync=trueDB::SyncWAL()

问:如何知道 RocksDB 数据库中存储的密钥数量?

答:用于获取列族中存储的估计密钥数,或用于获取整个 RocksDB 数据库中存储的估计密钥数。GetIntProperty(cf_handle, “rocksdb.estimate-num-keys”)GetAggregatedIntProperty(“rocksdb.estimate-num-keys", &num_keys)

问:为什么 GetIntProperty 只能返回 RocksDB 数据库中估计数量的键?

答:在任何 LSM 数据库(如 RocksDB)中获取准确数量的密钥是一个具有挑战性的问题,因为它们具有重复的密钥和删除条目(即逻辑删除),需要完全压缩才能获得准确数量的密钥。此外,如果 RocksDB 数据库包含合并运算符,它还会使估计的键数不太准确。

资源管理

问:迭代器持有多少资源,何时释放这些资源?

答:迭代器将数据块和内存表都保存在内存中。每个迭代器持有的资源包括:

迭代器当前指向的数据块。请参阅 https://github.com/facebook/rocksdb/wiki/Memory-usage-in-RocksDB#blocks-pinned-by-iterators
创建迭代器时存在的内存表,即使在刷新内存表之后也是如此。
创建迭代器时磁盘上存在的所有 SST 文件,即使它们已压缩。
删除迭代器时,将释放这些资源。

问:如何估算数据库中索引块和筛选器块的总大小?

答:对于离线数据库,将显示特定 sst 文件的索引和过滤器大小。您可以对所有数据库进行汇总。对于正在运行的数据库,您可以从数据库属性 中获取。或者调用并汇总单个文件的索引和过滤器块大小。"sst_dump --show_properties --command=none"kAggregatedTablePropertiesDB::GetPropertiesOfAllTables()

问:RocksDB 能否告诉我们数据库中的密钥总数?还是范围内键的总数?

答:RocksDB 可以通过 DB 属性估算密钥数量。请注意,当存在合并运算符、覆盖现有键或删除不存在的键时,此估计值可能相差甚远。“rocksdb.estimate-num-keys”

估计范围内键总数的最佳方法是首先通过调用 估计范围的大小,然后从中估计键数。DB::GetApproximateSizes()

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值