跳到主要内容

键值存储概述

键值(KV)存储是众多数据库与存储系统的基础,其选型对性能、可扩展性及运维复杂度具有显著影响。

1. 键值存储的类型

键值存储可大致分为以下三类:

1.1 内存型键值存储

  • 示例:std::unordered_mapfolly::F14、自定义哈希表。
  • 特性:
  • 延迟极低(纳秒至微秒级)。
  • 无持久化能力,除非结合快照或预写日志(WAL)。
  • 无默认排序保证,需显式实现。
  • 适用场景:缓存、快速索引、临时状态存储。

1.2 嵌入式磁盘键值存储(基于LSM树/ B+树)

  • 示例:RocksDB、LevelDB、LMDB。
  • 特性:
  • 数据持久化存储于磁盘。
  • 支持超出内存容量的大规模数据。
  • 提供键有序性(支持前缀/范围扫描)。
  • 不同程度支持快照、备份及事务功能。

1.3 分布式键值存储

  • 示例:TiKV、RocksDB+Raft、Cassandra(类KV接口)。
  • 特性:
  • 支持跨节点水平扩展。
  • 内置副本复制、故障转移及一致性保障机制。
  • 内部通常基于嵌入式键值引擎构建。

2. 聚焦对比:RocksDB、LevelDB、LMDB

特性/引擎RocksDBLevelDBLMDB
存储类型日志结构合并树(LSM-tree)日志结构合并树(LSM-tree)B+树(内存映射)
最大数据库容量10–100 TB+~10 TB~16 TB(64位操作系统)
写入吞吐量50k–200k 操作/秒(SSD)30k–100k 操作/秒5k–50k 操作/秒(磁盘存储)
读取吞吐量100k–500k 点查询/秒50k–200k 点查询/秒50k–200k 点查询/秒
范围读取/扫描性能200–800 MB/秒(前缀优化)100–400 MB/秒100–400 MB/秒
内存占用可配置的内存表 + 块缓存内存表 + 块缓存整个数据库映射至地址空间
持久化与耐用性预写日志(WAL)+ 排序字符串表(SST)预写日志(WAL)+ 排序字符串表(SST)内存映射 + 同步机制
事务支持单键原子性、批量写入单键原子性、批量写入ACID特性、多版本并发控制(MVCC)
列族支持
最适场景大规模、高写入负载、前缀扫描、多列族需求中小型数据库、嵌入式场景读多写少负载、ACID合规要求、内存映射场景
备注可配置项丰富;适合LSM树深度调优设计简洁;可配置项少;压缩调优受限读取延迟极低;若文件系统同步缓慢,写入会阻塞

3. 核心运维指南

生产环境部署时,不同键值引擎的运维重点存在差异:

3.1 RocksDB

(1)SST文件管理

  • RocksDB按列族生成LSM树的SST文件。
  • 频繁的压缩操作可能产生大量小SST文件,过多小文件会影响读取性能并增加磁盘占用。
  • 非必要情况下避免创建过多列族,优先通过键前缀实现逻辑隔离。

(2)备份与快照

  • 优先使用基于快照的备份,适用于增量复制或快速时间点备份。
  • 限制文件级全量备份(SST文件 checkpoint)的频率,避免造成高I/O负载。

(3)范围扫描的键设计

  • 固定长度的前缀键可提升前缀扫描吞吐量
  • 考虑按键范围对大规模数据集进行分区,简化压缩与备份操作。

(4)I/O与内存调优

  • 调整内存表大小、块缓存、压缩线程数,以匹配SSD的I/O能力。
  • 监控SST文件大小分布及写入放大情况。

3.2 LMDB

(1)单文件简化特性

  • LMDB每个数据库(或环境)对应一个内存映射文件。
  • 运维管理简单,无需执行压缩操作。

(2)读多写少负载优化

  • 最适用于读操作占主导的场景,多读者可并发访问且无锁竞争。

(3)写入注意事项

  • 单写者限制意味着:若磁盘同步缓慢,写入峰值可能阻塞读操作。
  • 若需高写入并发,避免将多个LMDB数据库部署在同一文件中。

3.3 通用运维要点

  • 小规模键值存储场景下,LMDB更简洁,运维成本更低。
  • 大规模或高写入负载场景下,RocksDB提供更高的灵活性与可配置性,但需监控SST文件、列族及压缩周期。
  • 使用快照与增量备份可降低I/O影响,在不暂停写入的情况下保障备份一致性。