RocksDB

RocksDB 是一个高性能的键值存储引擎,由 Facebook 开发并开源,起源于 Google 的 LevelDB。
发展历程
  • 2012 年:Facebook 开始在 LevelDB 的基础上开发 RocksDB。
  • 2013 年:RocksDB 首次开源,成为 GitHub 上的一个项目。
  • 持续改进:自开源以来,RocksDB 得到了社区的广泛关注和贡献,Facebook 也持续改进和优化 RocksDB,以满足不断变化的需求。
LevelDB
LevelDB 是由 Google 开发的,它是一个基于磁盘的键值存储库,使用 LSM-Tree(Log-Structured Merge Tree)数据结构。LevelDB 设计简洁、性能优秀,适用于嵌入式系统,但在某些高负载情况下,性能和功能不符合 Facebook 的需求。
Facebook 的需求
在 2012 年,Facebook 需要一个能够处理大量数据、高并发读写请求的存储引擎。LevelDB 虽然性能优异,但在面对 Facebook 的海量数据和高并发请求时,暴露出了一些瓶颈和问题,如:
  • 写入放大(Write Amplification):LevelDB 在高写入负载下的性能瓶颈。
  • 读放大(Read Amplification):在某些查询模式下,读取性能不佳。
  • 缺乏多线程支持:LevelDB 的单线程设计难以充分利用多核处理器的性能。
RocksDB 的诞生
为了满足自身的需求,Facebook 在 LevelDB 的基础上进行了大量优化和扩展,最终开发出了 RocksDB。以下是一些关键的改进:
  • 多线程支持:RocksDB 通过引入多线程机制来提升并发性能,充分利用多核处理器的优势。例如,多线程 Compaction 和多线程写入操作。
  • 更好的写入性能:提升写入性能是 RocksDB 的核心目标之一,通过优化 LSM-Tree 和引入多种写入缓冲机制来减少写入放大。
  • 更高效的压缩:提供多种压缩算法和多级别压缩策略,用户可以根据具体需求选择合适的压缩方式,进一步优化存储效率。
  • 丰富的配置选项:RocksDB 提供了大量的配置选项,允许用户根据具体场景进行微调和优化,例如内存管理、缓存大小、写入缓冲区大小等。
  • 列族支持:引入了列族(Column Families)的概念,允许用户将数据按逻辑分组,提供更灵活的数据组织方式。
  • 更强的持久化机制:通过改进 Write-Ahead Log (WAL) 和快照机制,RocksDB 提供了更强的数据持久化和恢复能力。

2. 应用场景

2.1. 特性

  • 高性能:RocksDB 是为快速读写操作优化的,特别适用于需要低延迟和高吞吐量的应用场景,如实时分析、在线事务处理等。
  • 可嵌入:它是一个嵌入式数据库,这意味着它可以直接嵌入到应用程序中,而不需要运行一个独立的服务器进程。这使得它非常适合于需要紧密集成数据库存储的应用程序。
  • 灵活的配置:RocksDB 提供了多种配置选项,允许开发者根据具体需求调整读写性能、内存使用、磁盘使用等。
  • 支持多种存储引擎:除了默认的磁盘存储引擎外,RocksDB 还支持基于内存的存储引擎,以满足不同的性能需求。
  • 丰富的功能:包括快照、事务、列族、压缩、合并操作等,这些功能使得 RocksDB 能够应对各种复杂的应用场景。
  • 横向扩展:虽然 RocksDB 本身是一个嵌入式数据库,但它可以通过集成到分布式系统(如 Apache Cassandra、TiDB 等)中实现横向扩展。

2.2. 应用场景

RocksDB 常用在以下场景中:
  • 缓存存储:由于其快速的读写性能,RocksDB 经常被用作缓存存储解决方案。
  • 实时数据分析:适用于需要低延迟数据写入和查询的实时分析系统。
  • 嵌入式设备:因其嵌入式特性,RocksDB 常用于需要本地数据存储的嵌入式设备中。
  • 分布式系统:作为存储引擎集成到分布式数据库和文件系统中。
1. 日志存储和处理
在日志存储和处理系统中,RocksDB 可以处理高频率的写入操作,并提供高效的数据持久化和查询能力。
特点和优势:
  • 高效写入:RocksDB 的 LSM-Tree 结构和写缓冲机制可以处理高频率的写入操作,减少写入放大。
  • 持久化:通过 WAL 日志和快照机制,确保数据在系统崩溃时也能恢复。
  • 压缩:支持多种压缩算法,减少存储空间消耗。
示例:
  • Kafka 使用 RocksDB 作为内部的状态存储引擎,用于存储日志和偏移量信息。
2. 缓存系统
RocksDB 可以作为持久化缓存层,结合内存缓存和磁盘存储的优势。
特点和优势:
  • 持久化缓存:数据可以永久存储在磁盘上,减少数据丢失的风险。
  • 内存管理:灵活的内存管理策略,可以根据内存大小调整缓存策略。
  • 高性能读取:通过内存中的 memtable 和 block cache 提供高效的读取性能。
示例:
  • Facebook 的 McDipper:一个分布式缓存系统,使用 RocksDB 作为持久化存储。
3. 大数据和分布式系统
在大数据处理和分布式系统中,RocksDB 可以作为高效的存储引擎,支持高并发读写操作。
特点和优势:
  • 多线程支持:充分利用多核处理器的优势,提升并发性能。
  • 灵活配置:提供大量的配置选项,可以根据具体场景进行优化。
  • 事务支持:基本的事务支持,确保数据一致性。
示例:
  • Apache Flink:一个流处理框架,使用 RocksDB 作为状态存储引擎。
  • CockroachDB:一个分布式 SQL 数据库,使用 RocksDB 作为底层存储引擎。
4. 物联网和边缘计算
在资源受限的物联网设备和边缘计算环境中,RocksDB 提供高效的数据存储和处理能力。
特点和优势:
  • 小内存占用:适合内存有限的设备。
  • 高效写入和读取:适合频繁的传感器数据收集和查询。
  • 嵌入式:无需独立服务,可以直接嵌入到应用程序中。
示例:
物联网网关设备:收集传感器数据并进行本地存储和处理。
5. NoSQL 数据库
许多 NoSQL 数据库使用 RocksDB 作为存储引擎,提供高效的键值存储和查询能力。
特点和优势:
  • 高并发支持:多线程写入和读取,提升并发性能。
  • 灵活的键值存储:支持多种数据类型和复杂查询。
  • 持久化和压缩:确保数据安全并优化存储空间。
示例:
  • TiDB:一个分布式 SQL 数据库,使用 RocksDB 作为底层存储。
  • ScyllaDB:一个高性能的 NoSQL 数据库,也使用 RocksDB 作为存储引擎。

3.配置调优

3.1. 配置调优

RocksDB 提供了许多可配置的选项,用于优化数据库的性能、内存使用和磁盘 I/O。以下是一些关键的调优配置选项,涵盖了内存管理、Compaction 策略、WAL(Write-Ahead Log)日志、Block 缓存、数据压缩和并发控制等方面:

3.1.1. 内存管理

MemTable 配置:
  • setWriteBufferSize: 控制 MemTable 的大小,以平衡写入性能和 Compaction 频率。
  • setMaxWriteBufferNumber: 设置同时存在的 MemTable 数量,以处理并发写入。
  • setMinWriteBufferNumberToMerge: 设置合并到磁盘前需要的最小 MemTable 数量。Table Format 配置:
  • BlockBasedTableConfig: 配置 SSTable 文件的 Block 大小,以优化读取性能。

3.1.2. Compaction 策略

Level Compaction
  • setLevelCompactionDynamicLevelBytes: 动态调整每层的大小,以平衡 Compaction 频率和读写放大。
  • setMaxBytesForLevelBase 和 setMaxBytesForLevelMultiplier: 设置各级别的目标大小和倍数,控制 Compaction 触发条件。
  • setCompactionPri: 设置 Compaction 优先级,如 BySize、ByCompensatedSize 等。
Universal Compaction
  • setCompactionStyle: 设置为 CompactionStyle.UNIVERSAL,适用于写密集型应用。
  • setUniversalCompactionOptions: 配置 Universal Compaction 的相关参数,如合并策略、阈值等。

3.1.3. WAL 配置

  • setWalDir: 设置 WAL 日志的存储路径。
  • setWalTtlSeconds 和 setWalSizeLimitMB: 控制 WAL 日志的保留时间和大小,以平衡数据安全和磁盘使用。

3.1.4. Block Cache

  • LRUCache: 创建和配置 Block Cache,用于缓存 SSTable 中的数据块,提高读性能。
  • setBlockSize: 设置 Block 大小,影响 Block Cache 的利用率。
  • setPinL0FilterAndIndexBlocksInCache: 是否将 Level 0 的过滤器和索引块保留在 Block Cache 中。

3.1.5. 数据压缩

  • setCompression: 设置数据压缩算法,如 NoCompression、Snappy、Zlib、LZ4 或 Zstd,以节省磁盘空间。
  • setCompressionPerLevel: 针对不同级别设置不同的压缩算法。

3.1.6. 并发控制

  • setMaxBackgroundJobs: 设置后台任务的最大并发数,包括 Compaction 和刷写操作。
  • setMaxBackgroundCompactions: 设置最大 Compaction 线程数。
  • setMaxBackgroundFlushes: 设置最大刷写线程数。

3.1.7. 其他优化

  • useFsync: 是否在写入时使用 fsync,以确保数据的持久性。
  • setTableFormatConfig: 配置 SSTable 的其他属性,如过滤器类型、索引间隔等。

3.1.8. 示例代码

3.2. MemTable、Block Cache

功能
  • MemTable:数据首先被写入 MemTable,然后再根据一定的策略刷写到磁盘生成 SSTable 文件。主要用于存储新写入的数据,临时存储在内存中并定期刷写到磁盘。优化写性能。
  • Block Cache:主要用于缓存从磁盘读取的数据块,减少后续读取相同数据块的磁盘 I/O。优化读性能。
操作路径
  • MemTable:写操作首先写入 MemTable,读操作首先检查 MemTable。
  • Block Cache:读操作在MemTable之后查不到之后会读 Block Cache,如果命中则返回缓存数据;否则从磁盘读取并缓存。
持久性
  • MemTable:数据最终会被持久化到磁盘生成 SSTable 文件。
  • Block Cache:缓存的数据块不具备持久性,缓存失效或系统重启后需要重新加载。
配置
  • MemTable:通过 setWriteBufferSize 和 setMaxWriteBufferNumber 配置大小和数量。
  • Block Cache:通过 LRUCache 配置大小。
配置建议
MemTable:
  • 在写密集型场景中,适当增加 MemTable 大小和数量,可以提高写入性能和减少刷写频率。
  • 在内存有限的情况下,配置适当的 MemTable 大小,确保内存使用的合理性,避免内存不足。
Block Cache:
  • 在读密集型场景中,适当增加 Block Cache 大小,可以提高读缓存命中率和读性能。
  • 在内存有限的情况下,配置适当的 Block Cache 大小,确保内存使用的合理性,避免内存不足。

3.3. 读顺序

在 RocksDB 中,读操作的流程涉及多个步骤,主要目的是尽可能快速地找到所需的数据。具体步骤如下:
1.查询 MemTable
首先,RocksDB 会在 MemTable 中查找数据。MemTable 存储的是最近的写操作数据,由于在内存中查询速度非常快,所以这是第一步。
如果在 MemTable 中找不到数据,RocksDB 接着会在 Immutable MemTable 中查找。Immutable MemTable 是已经写满并准备刷到磁盘但尚未完成的 MemTable。
2.查询 Block Cache
如果在 MemTable 和 Immutable MemTable 中都没有找到数据,RocksDB 会查找 Block Cache。Block Cache 存储的是从 SSTable 文件中读取的数据块(block),用于加速读操作。
Block Cache 是基于 LRU(Least Recently Used)策略管理的,旨在保留最近使用的数据块,以提高缓存命中率。
3.查询 SSTable 文件
如果数据不在 Block Cache 中,RocksDB 会从磁盘上的 SSTable 文件中查找。首先会查找每层的索引和过滤器(如布隆过滤器)来确定数据可能存在的文件和位置。
从 SSTable 文件中读取数据块时,RocksDB 会将这些数据块加载到 Block Cache 中,以便后续访问更快。
4.合并数据
如果在多个位置找到数据版本(例如在 MemTable 和 SSTable 中同时存在),RocksDB 会根据数据的序列号(sequence number)和操作类型(如 PUT 或 DELETE)来确定最终返回的数据。

4. spring使用

4.1. 配置类

RocksDB 是一个嵌入式数据库,这意味着它不需要单独的服务器进程。一般情况下,你只需要指定数据存储目录和一些配置选项。
pom
调优选项解释
MemTable 配置
  • setWriteBufferSize: 设置每个 MemTable 的大小。例如,这里设置为 64MB。
  • setMaxWriteBufferNumber: 设置同时存在的最大 MemTable 数量,这里设置为 3。
  • setMinWriteBufferNumberToMerge: 设置合并 MemTable 的最小数量。
Block Cache 配置
  • 使用 LRUCache 进行 Block Cache 的配置,这里设置为 128MB。
Compaction 策略
  • setLevelCompactionDynamicLevelBytes: 启用动态调整每层大小的 Compaction 策略。
  • setMaxBackgroundCompactions: 设置最大后台 Compaction 线程数。
  • setMaxBackgroundFlushes: 设置最大后台刷写线程数。
WAL 配置
  • setWalDir: 设置 WAL 文件的存储路径,以确保数据的持久性。
通过这些配置,您可以根据业务需求和系统资源情况,合理调整 RocksDB 的参数,提升其在 Spring 项目中的性能。

4.1. 操作类

你可以通过注入 RocksDB bean 来在 Spring 中使用 RocksDB 进行数据操作。以下是一个简单的示例,展示了如何进行基本的增删改查操作:
Loading...
目录
文章列表
王小扬博客
产品
Think
Git
软件开发
计算机网络
CI
DB
设计
缓存
Docker
Node
操作系统
Java
大前端
Nestjs
其他
PHP