RocksDB内存管理 #
一、内存使用概述 #
1.1 内存组成 #
text
RocksDB内存使用:
┌─────────────────────────────────────────────────┐
│ 总内存使用 │
├─────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────┐ │
│ │ Block Cache │ │
│ │ (数据块缓存) │ │
│ └─────────────────────────────────────────┘ │
├─────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────┐ │
│ │ MemTable │ │
│ │ (写入缓冲) │ │
│ └─────────────────────────────────────────┘ │
├─────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────┐ │
│ │ Index & Filter │ │
│ │ (索引和过滤器) │ │
│ └─────────────────────────────────────────┘ │
├─────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────┐ │
│ │ 其他开销 │ │
│ │ (跳表、锁等) │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
1.2 内存比例建议 #
| 组件 | 建议比例 | 说明 |
|---|---|---|
| Block Cache | 40-50% | 缓存热数据 |
| MemTable | 20-30% | 写入缓冲 |
| Index & Filter | 10-20% | 加速查找 |
| 其他 | 5-10% | 系统开销 |
二、Block Cache #
2.1 创建Block Cache #
cpp
#include <rocksdb/cache.h>
#include <rocksdb/table.h>
// LRU缓存
std::shared_ptr<rocksdb::Cache> CreateLRUCache(size_t size) {
return rocksdb::NewLRUCache(
size, // 缓存大小
8, // 分片数(减少锁竞争)
false, // 是否使用高优先级
0.0 // 高优先级比例
);
}
// 使用
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = CreateLRUCache(1024 * 1024 * 1024); // 1GB
2.2 Block Cache配置 #
cpp
#include <rocksdb/table.h>
rocksdb::BlockBasedTableOptions GetBlockCacheOptions() {
rocksdb::BlockBasedTableOptions options;
// 主缓存
options.block_cache = rocksdb::NewLRUCache(
1024 * 1024 * 1024, // 1GB
16 // 16分片
);
// 压缩块缓存
options.block_cache_compressed = rocksdb::NewLRUCache(
256 * 1024 * 1024 // 256MB
);
// Pin L0的Filter和Index
options.pin_l0_filter_and_index_blocks_in_cache = true;
// Pin顶层Index
options.pin_top_level_index_and_filter = true;
return options;
}
2.3 缓存优先级 #
cpp
#include <rocksdb/cache.h>
// 设置缓存优先级
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = rocksdb::NewLRUCache(
1024 * 1024 * 1024,
8,
true, // 使用高优先级
0.5 // 50%高优先级
);
// 高优先级用于:
// - 索引块
// - 过滤器块
// - 热点数据块
2.4 缓存统计 #
cpp
#include <rocksdb/cache.h>
#include <iostream>
void PrintCacheStats(const std::shared_ptr<rocksdb::Cache>& cache) {
rocksdb::Cache::CacheStats stats;
cache->GetStats(&stats);
std::cout << "Cache usage: " << stats.cache_usage << std::endl;
std::cout << "Pinned usage: " << stats.pinned_usage << std::endl;
std::cout << "Hit rate: " <<
(double)stats.hit_count / (stats.hit_count + stats.miss_count) << std::endl;
}
三、MemTable内存 #
3.1 MemTable大小配置 #
cpp
#include <rocksdb/options.h>
rocksdb::Options GetMemTableOptions() {
rocksdb::Options options;
// 单个MemTable大小
options.write_buffer_size = 64 * 1024 * 1024; // 64MB
// 最大MemTable数量
options.max_write_buffer_number = 4;
// 最小合并数量
options.min_write_buffer_number_to_merge = 2;
// 最大内存占用 = write_buffer_size × max_write_buffer_number
// = 64MB × 4 = 256MB
return options;
}
3.2 MemTable内存计算 #
text
MemTable内存占用计算:
1. 数据存储
- 键值对数据
- 跳表节点
2. 索引开销
- 跳表多层索引
- 约10-20%额外开销
3. 总占用
MemTable内存 ≈ 数据大小 × 1.2
示例:
write_buffer_size = 64MB
实际内存占用 ≈ 64MB × 1.2 = 76.8MB
3.3 MemTable变体内存 #
cpp
#include <rocksdb/memtablerep.h>
// 跳表(默认)- 内存效率中等
options.memtable_factory.reset(new rocksdb::SkipListFactory());
// 向量 - 内存效率低,适合小数据
options.memtable_factory.reset(new rocksdb::VectorRepFactory());
// 哈希链表 - 内存效率高
options.memtable_factory.reset(
rocksdb::NewHashLinkListRepFactory(10000)
);
四、索引和过滤器内存 #
4.1 索引块内存 #
cpp
#include <rocksdb/table.h>
rocksdb::BlockBasedTableOptions GetIndexOptions() {
rocksdb::BlockBasedTableOptions options;
// 索引类型
options.index_type = rocksdb::BlockBasedTableOptions::kBinarySearch;
// 索引块大小
options.index_block_restart_interval = 1;
// Pin索引到缓存
options.pin_l0_filter_and_index_blocks_in_cache = true;
return options;
}
4.2 过滤器内存 #
cpp
#include <rocksdb/table.h>
#include <rocksdb/filter_policy.h>
rocksdb::BlockBasedTableOptions GetFilterOptions() {
rocksdb::BlockBasedTableOptions options;
// 布隆过滤器
options.filter_policy.reset(
rocksdb::NewBloomFilterPolicy(10) // 10 bits per key
);
// 内存占用计算:
// 每个key 10 bits
// 100万keys = 10M bits ≈ 1.25MB
// 优化内存
options.optimize_filters_for_memory = true;
return options;
}
4.3 减少索引内存 #
cpp
#include <rocksdb/table.h>
rocksdb::BlockBasedTableOptions GetReducedIndexOptions() {
rocksdb::BlockBasedTableOptions options;
// 使用分区索引
options.index_type = rocksdb::BlockBasedTableOptions::kTwoLevelIndexSearch;
// 增大索引块大小
options.index_block_restart_interval = 16;
// 使用哈希索引(适合点查询)
options.index_type = rocksdb::BlockBasedTableOptions::kHashSearch;
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(5));
return options;
}
五、内存限制 #
5.1 设置内存限制 #
cpp
#include <rocksdb/db.h>
#include <rocksdb/options.h>
void SetMemoryLimit(rocksdb::DB* db, size_t limit) {
// 设置Block Cache大小限制
auto cache = db->GetOptions().table_factory->GetOptions<rocksdb::BlockBasedTableOptions>()->block_cache;
cache->SetCapacity(limit);
}
// 监控内存使用
void MonitorMemoryUsage(rocksdb::DB* db) {
uint64_t memtable_usage;
db->GetIntProperty("rocksdb.cur-size-all-mem-tables", &memtable_usage);
uint64_t block_cache_usage;
db->GetIntProperty("rocksdb.block-cache-usage", &block_cache_usage);
std::cout << "MemTable: " << memtable_usage / 1024 / 1024 << " MB" << std::endl;
std::cout << "Block Cache: " << block_cache_usage / 1024 / 1024 << " MB" << std::endl;
}
5.2 写入限速 #
cpp
#include <rocksdb/options.h>
rocksdb::Options GetWriteLimitOptions() {
rocksdb::Options options;
// MemTable数量限制
options.max_write_buffer_number = 4;
// 写入减速触发
options.level0_slowdown_writes_trigger = 20;
// 写入停止触发
options.level0_stop_writes_trigger = 36;
return options;
}
六、内存优化策略 #
6.1 内存敏感场景 #
cpp
#include <rocksdb/options.h>
#include <rocksdb/table.h>
rocksdb::Options GetMemoryOptimizedOptions() {
rocksdb::Options options;
// 减小MemTable
options.write_buffer_size = 16 * 1024 * 1024; // 16MB
options.max_write_buffer_number = 2;
// 减小Block Cache
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = rocksdb::NewLRUCache(256 * 1024 * 1024); // 256MB
// 使用高压缩比
options.compression = rocksdb::CompressionType::kZSTD;
// 减少索引内存
table_options.index_block_restart_interval = 16;
options.table_factory.reset(
rocksdb::NewBlockBasedTableFactory(table_options)
);
return options;
}
6.2 内存充足场景 #
cpp
#include <rocksdb/options.h>
#include <rocksdb/table.h>
rocksdb::Options GetMemoryRichOptions() {
rocksdb::Options options;
// 大MemTable
options.write_buffer_size = 256 * 1024 * 1024; // 256MB
options.max_write_buffer_number = 8;
// 大Block Cache
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = rocksdb::NewLRUCache(4 * 1024 * 1024 * 1024); // 4GB
table_options.block_cache_compressed = rocksdb::NewLRUCache(512 * 1024 * 1024);
// Pin更多数据
table_options.pin_l0_filter_and_index_blocks_in_cache = true;
table_options.pin_top_level_index_and_filter = true;
options.table_factory.reset(
rocksdb::NewBlockBasedTableFactory(table_options)
);
return options;
}
七、内存监控 #
7.1 内存指标 #
cpp
#include <rocksdb/db.h>
#include <iostream>
void PrintMemoryStats(rocksdb::DB* db) {
uint64_t value;
// MemTable内存
db->GetIntProperty("rocksdb.cur-size-all-mem-tables", &value);
std::cout << "MemTable memory: " << value / 1024 / 1024 << " MB" << std::endl;
// Block Cache使用
db->GetIntProperty("rocksdb.block-cache-usage", &value);
std::cout << "Block cache usage: " << value / 1024 / 1024 << " MB" << std::endl;
// Block CachePin
db->GetIntProperty("rocksdb.block-cache-pinned-usage", &value);
std::cout << "Block cache pinned: " << value / 1024 / 1024 << " MB" << std::endl;
// 活跃MemTable数量
db->GetIntProperty("rocksdb.num-active-mem-table", &value);
std::cout << "Active MemTables: " << value << std::endl;
// Immutable MemTable数量
db->GetIntProperty("rocksdb.num-immutable-mem-table", &value);
std::cout << "Immutable MemTables: " << value << std::endl;
}
7.2 内存统计 #
cpp
#include <rocksdb/statistics.h>
void PrintMemoryStatistics(rocksdb::DB* db) {
auto stats = db->GetOptions().statistics;
// Block Cache命中
uint64_t hits = stats->getTickerCount(rocksdb::BLOCK_CACHE_HIT);
uint64_t misses = stats->getTickerCount(rocksdb::BLOCK_CACHE_MISS);
double hit_rate = (double)hits / (hits + misses) * 100;
std::cout << "Block cache hit rate: " << hit_rate << "%" << std::endl;
// MemTable命中
hits = stats->getTickerCount(rocksdb::MEMTABLE_HIT);
misses = stats->getTickerCount(rocksdb::MEMTABLE_MISS);
hit_rate = (double)hits / (hits + misses) * 100;
std::cout << "MemTable hit rate: " << hit_rate << "%" << std::endl;
}
八、最佳实践 #
8.1 内存配置建议 #
| 场景 | Block Cache | MemTable | 建议 |
|---|---|---|---|
| 读密集 | 50-60% | 15-20% | 大缓存 |
| 写密集 | 30-40% | 30-40% | 大MemTable |
| 平衡 | 40-50% | 25-30% | 均衡配置 |
| 内存受限 | 30-40% | 15-20% | 高压缩比 |
8.2 内存调优步骤 #
- 评估可用内存:确定总内存预算
- 分配组件内存:按比例分配各组件
- 监控内存使用:观察实际使用情况
- 调整优化:根据监控结果调整
- 验证效果:确认性能提升
九、总结 #
9.1 内存组件 #
| 组件 | 作用 | 配置参数 |
|---|---|---|
| Block Cache | 缓存热数据 | block_cache |
| MemTable | 写入缓冲 | write_buffer_size |
| Index | 加速查找 | index_block_restart_interval |
| Filter | 快速排除 | filter_policy |
9.2 关键要点 #
- 合理分配:按场景分配内存比例
- 监控使用:持续监控内存指标
- 及时调整:根据实际情况优化
- 避免溢出:设置合理的限制
- 权衡取舍:平衡各组件内存
下一步,让我们学习缓存策略!
最后更新:2026-03-27